From d118b2bff198d686b6b3296e68ee9a928be536c0 Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Sun, 27 Nov 2022 08:21:38 +0200 Subject: [PATCH] Remove unused patches Signed-off-by: Alexander Bokovoy --- ...-Dogtag-return-XML-for-ipa-cert-find.patch | 33 - ...DAP-password-grace-when-the-password.patch | 56 - ...acelimit-does-not-prevent-LDAP-binds.patch | 125 - 0003-webui-Allow-grace-login-limit.patch | 56 - ...er-Fix-use-of-nameservers-with-ports.patch | 137 - ...al_policy_on_group_pw_policies_#6419.patch | 231 - freeipa-bz1948034.patch | 114 - freeipa-fix-389-ds-2.0.5-upgrade.patch | 255 - freeipa-fix-missing-creds.patch | 28 - freeipa-harden-pac-2.patch | 222 - freeipa-harden-pac.patch | 4223 ----------------- 11 files changed, 5480 deletions(-) delete mode 100644 0001-Make-Dogtag-return-XML-for-ipa-cert-find.patch delete mode 100644 0001-Only-calculate-LDAP-password-grace-when-the-password.patch delete mode 100644 0002-Disabling-gracelimit-does-not-prevent-LDAP-binds.patch delete mode 100644 0003-webui-Allow-grace-login-limit.patch delete mode 100644 0004-DNSResolver-Fix-use-of-nameservers-with-ports.patch delete mode 100644 0005_Set_passwordgracelimit_to_match_global_policy_on_group_pw_policies_#6419.patch delete mode 100644 freeipa-bz1948034.patch delete mode 100644 freeipa-fix-389-ds-2.0.5-upgrade.patch delete mode 100644 freeipa-fix-missing-creds.patch delete mode 100644 freeipa-harden-pac-2.patch delete mode 100644 freeipa-harden-pac.patch diff --git a/0001-Make-Dogtag-return-XML-for-ipa-cert-find.patch b/0001-Make-Dogtag-return-XML-for-ipa-cert-find.patch deleted file mode 100644 index ee20cf9..0000000 --- a/0001-Make-Dogtag-return-XML-for-ipa-cert-find.patch +++ /dev/null @@ -1,33 +0,0 @@ -From d43b513927d6dd0a12464dd24287ce40ccaf33e4 Mon Sep 17 00:00:00 2001 -From: Chris Kelley -Date: Fri, 10 Sep 2021 16:47:22 +0100 -Subject: [PATCH] Make Dogtag return XML for ipa cert-find - -Using JSON by default within Dogtag appears to cause ipa cert-find to -return JSON, when the request was made with XML. We can request that XML -is returned as before by specifying so in the request header. - -Fixes: https://pagure.io/freeipa/issue/8980 -Signed-off-by: Chris Kelley -Reviewed-By: Francois Cami ---- - ipaserver/plugins/dogtag.py | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/ipaserver/plugins/dogtag.py b/ipaserver/plugins/dogtag.py -index be2e4bb4e..b4feddfac 100644 ---- a/ipaserver/plugins/dogtag.py -+++ b/ipaserver/plugins/dogtag.py -@@ -1832,7 +1832,8 @@ class ra(rabase.rabase, RestClient): - method='POST', - headers={'Accept-Encoding': 'gzip, deflate', - 'User-Agent': 'IPA', -- 'Content-Type': 'application/xml'}, -+ 'Content-Type': 'application/xml', -+ 'Accept': 'application/xml'}, - body=payload - ) - --- -2.31.1 - diff --git a/0001-Only-calculate-LDAP-password-grace-when-the-password.patch b/0001-Only-calculate-LDAP-password-grace-when-the-password.patch deleted file mode 100644 index 5e5d9d7..0000000 --- a/0001-Only-calculate-LDAP-password-grace-when-the-password.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 22d1392a8a0d2887c389dcd78be06104cff88d30 Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Wed, 29 Jun 2022 13:25:55 +0000 -Subject: [PATCH] Only calculate LDAP password grace when the password is - expired - -The user's pwd expiration was retrieved but inadvertently was never -compared to current time. So any LDAP bind, including from the -IPA API, counted against the grace period. There is no need to go -through the graceperiod code for non-expired passwords. - -https://pagure.io/freeipa/issue/1539 - -Signed-off-by: Rob Crittenden -Reviewed-By: Florence Blanc-Renaud ---- - .../ipa-graceperiod/ipa_graceperiod.c | 12 +++++++++--- - 1 file changed, 9 insertions(+), 3 deletions(-) - -diff --git a/daemons/ipa-slapi-plugins/ipa-graceperiod/ipa_graceperiod.c b/daemons/ipa-slapi-plugins/ipa-graceperiod/ipa_graceperiod.c -index 0860b5c20..a3f57cb4b 100644 ---- a/daemons/ipa-slapi-plugins/ipa-graceperiod/ipa_graceperiod.c -+++ b/daemons/ipa-slapi-plugins/ipa-graceperiod/ipa_graceperiod.c -@@ -359,7 +359,8 @@ static int ipagraceperiod_preop(Slapi_PBlock *pb) - Slapi_ValueSet *values = NULL; - long grace_limit = 0; - int grace_user_time; -- char *pwd_expiration = NULL; -+ char *tmpstr = NULL; -+ time_t pwd_expiration; - int pwresponse_requested = 0; - Slapi_PBlock *pbtm = NULL; - Slapi_Mods *smods = NULL; -@@ -414,12 +415,17 @@ static int ipagraceperiod_preop(Slapi_PBlock *pb) - } - slapi_value_free(&objectclass); - -- pwd_expiration = slapi_entry_attr_get_charptr(target_entry, "krbPasswordExpiration"); -- if (pwd_expiration == NULL) { -+ tmpstr = slapi_entry_attr_get_charptr(target_entry, "krbPasswordExpiration"); -+ if (tmpstr == NULL) { - /* No expiration means nothing to do */ - LOG_TRACE("No krbPasswordExpiration for %s, nothing to do\n", dn); - goto done; - } -+ pwd_expiration = ipapwd_gentime_to_time_t(tmpstr); -+ if (pwd_expiration > time(NULL)) { -+ /* Not expired, nothing to see here */ -+ goto done; -+ } - - ldrc = ipagraceperiod_getpolicy(target_entry, &policy_entry, - &values, &actual_type_name, --- -2.31.1 - diff --git a/0002-Disabling-gracelimit-does-not-prevent-LDAP-binds.patch b/0002-Disabling-gracelimit-does-not-prevent-LDAP-binds.patch deleted file mode 100644 index bd6f518..0000000 --- a/0002-Disabling-gracelimit-does-not-prevent-LDAP-binds.patch +++ /dev/null @@ -1,125 +0,0 @@ -From 1bb4ff9ed2313fb3c2bd1418258c5bcec557b6a5 Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Thu, 21 Jul 2022 09:28:46 -0400 -Subject: [PATCH] Disabling gracelimit does not prevent LDAP binds - -Originally the code treated 0 as disabled. This was -changed during the review process to -1 but one remnant -was missed effetively allowing gracelimit 0 to also mean -disabled. - -Add explicit tests for testing with gracelimit = 0 and -gracelimit = -1. - -Also remove some extranous "str(self.master.domain.basedn)" -lines from some of the tests. - -Fixes: https://pagure.io/freeipa/issue/9206 - -Signed-off-by: Rob Crittenden -Reviewed-By: Francisco Trivino ---- - .../ipa-graceperiod/ipa_graceperiod.c | 2 +- - ipatests/test_integration/test_pwpolicy.py | 55 ++++++++++++++++++- - 2 files changed, 53 insertions(+), 4 deletions(-) - -diff --git a/daemons/ipa-slapi-plugins/ipa-graceperiod/ipa_graceperiod.c b/daemons/ipa-slapi-plugins/ipa-graceperiod/ipa_graceperiod.c -index a3f57cb4b..345e1dee7 100644 ---- a/daemons/ipa-slapi-plugins/ipa-graceperiod/ipa_graceperiod.c -+++ b/daemons/ipa-slapi-plugins/ipa-graceperiod/ipa_graceperiod.c -@@ -479,7 +479,7 @@ static int ipagraceperiod_preop(Slapi_PBlock *pb) - if (pwresponse_requested) { - slapi_pwpolicy_make_response_control(pb, -1, grace_limit - grace_user_time , -1); - } -- } else if ((grace_limit > 0) && (grace_user_time >= grace_limit)) { -+ } else if (grace_user_time >= grace_limit) { - LOG_TRACE("%s password is expired and out of grace limit\n", dn); - errstr = "Password is expired.\n"; - ret = LDAP_INVALID_CREDENTIALS; -diff --git a/ipatests/test_integration/test_pwpolicy.py b/ipatests/test_integration/test_pwpolicy.py -index 6d6698284..41d6e9070 100644 ---- a/ipatests/test_integration/test_pwpolicy.py -+++ b/ipatests/test_integration/test_pwpolicy.py -@@ -36,7 +36,7 @@ class TestPWPolicy(IntegrationTest): - cls.master.run_command(['ipa', 'group-add-member', POLICY, - '--users', USER]) - cls.master.run_command(['ipa', 'pwpolicy-add', POLICY, -- '--priority', '1']) -+ '--priority', '1', '--gracelimit', '-1']) - cls.master.run_command(['ipa', 'passwd', USER], - stdin_text='{password}\n{password}\n'.format( - password=PASSWORD -@@ -265,7 +265,6 @@ class TestPWPolicy(IntegrationTest): - - def test_graceperiod_expired(self): - """Test the LDAP bind grace period""" -- str(self.master.domain.basedn) - dn = "uid={user},cn=users,cn=accounts,{base_dn}".format( - user=USER, base_dn=str(self.master.domain.basedn)) - -@@ -308,7 +307,6 @@ class TestPWPolicy(IntegrationTest): - - def test_graceperiod_not_replicated(self): - """Test that the grace period is reset on password reset""" -- str(self.master.domain.basedn) - dn = "uid={user},cn=users,cn=accounts,{base_dn}".format( - user=USER, base_dn=str(self.master.domain.basedn)) - -@@ -341,3 +339,54 @@ class TestPWPolicy(IntegrationTest): - ) - assert 'passwordgraceusertime: 0' in result.stdout_text.lower() - self.reset_password(self.master) -+ -+ def test_graceperiod_zero(self): -+ """Test the LDAP bind with zero grace period""" -+ dn = "uid={user},cn=users,cn=accounts,{base_dn}".format( -+ user=USER, base_dn=str(self.master.domain.basedn)) -+ -+ self.master.run_command( -+ ["ipa", "pwpolicy-mod", POLICY, "--gracelimit", "0", ], -+ ) -+ -+ # Resetting the password will mark it as expired -+ self.reset_password(self.master) -+ -+ # Now grace is done and binds should fail. -+ result = self.master.run_command( -+ ["ldapsearch", "-e", "ppolicy", "-D", dn, -+ "-w", PASSWORD, "-b", dn], raiseonerr=False -+ ) -+ assert result.returncode == 49 -+ -+ assert 'Password is expired' in result.stderr_text -+ assert 'Password expired, 0 grace logins remain' in result.stderr_text -+ -+ def test_graceperiod_disabled(self): -+ """Test the LDAP bind with grace period disabled (-1)""" -+ str(self.master.domain.basedn) -+ dn = "uid={user},cn=users,cn=accounts,{base_dn}".format( -+ user=USER, base_dn=str(self.master.domain.basedn)) -+ -+ # This can fail if gracelimit is already -1 so ignore it -+ self.master.run_command( -+ ["ipa", "pwpolicy-mod", POLICY, "--gracelimit", "-1",], -+ raiseonerr=False, -+ ) -+ -+ # Ensure the password is expired -+ self.reset_password(self.master) -+ -+ result = self.kinit_as_user(self.master, PASSWORD, PASSWORD) -+ -+ for _i in range(0, 10): -+ result = self.master.run_command( -+ ["ldapsearch", "-e", "ppolicy", "-D", dn, -+ "-w", PASSWORD, "-b", dn] -+ ) -+ -+ # With graceperiod disabled it should not increment -+ result = tasks.ldapsearch_dm( -+ self.master, dn, ['passwordgraceusertime',], -+ ) -+ assert 'passwordgraceusertime: 0' in result.stdout_text.lower() --- -2.37.1 - diff --git a/0003-webui-Allow-grace-login-limit.patch b/0003-webui-Allow-grace-login-limit.patch deleted file mode 100644 index 9083175..0000000 --- a/0003-webui-Allow-grace-login-limit.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 7a1e1d9f1cb13679c28f12d05b156a08bcc4d856 Mon Sep 17 00:00:00 2001 -From: Carla Martinez -Date: Fri, 29 Jul 2022 13:16:16 +0200 -Subject: [PATCH] webui: Allow grace login limit - -There was no support for setting the grace login limit on the WebUI. The -only way to so was only via CLI: - - `ipa pwpolicy-mod --gracelimit=2 global_policy` - -Thus, the grace login limit must be updated from the policy section and -this will reflect also on the user settings (under the 'Password Policy' -section) - -Fixes: https://pagure.io/freeipa/issue/9211 - -Signed-off-by: Carla Martinez -Reviewed-By: Florence Blanc-Renaud ---- - install/ui/src/freeipa/policy.js | 3 +++ - install/ui/src/freeipa/user.js | 5 +++++ - 2 files changed, 8 insertions(+) - -diff --git a/install/ui/src/freeipa/policy.js b/install/ui/src/freeipa/policy.js -index fa2028a52..7ec103636 100644 ---- a/install/ui/src/freeipa/policy.js -+++ b/install/ui/src/freeipa/policy.js -@@ -72,6 +72,9 @@ return { - { - name: 'cospriority', - required: true -+ }, -+ { -+ name: 'passwordgracelimit' - } - ] - }] -diff --git a/install/ui/src/freeipa/user.js b/install/ui/src/freeipa/user.js -index a580db035..b47c97f72 100644 ---- a/install/ui/src/freeipa/user.js -+++ b/install/ui/src/freeipa/user.js -@@ -318,6 +318,11 @@ return { - label: '@mo-param:pwpolicy:krbpwdlockoutduration:label', - read_only: true, - measurement_unit: 'seconds' -+ }, -+ { -+ name: 'passwordgracelimit', -+ label: '@mo-param:pwpolicy:passwordgracelimit:label', -+ read_only: true - } - ] - }, --- -2.37.1 - diff --git a/0004-DNSResolver-Fix-use-of-nameservers-with-ports.patch b/0004-DNSResolver-Fix-use-of-nameservers-with-ports.patch deleted file mode 100644 index b75e79d..0000000 --- a/0004-DNSResolver-Fix-use-of-nameservers-with-ports.patch +++ /dev/null @@ -1,137 +0,0 @@ -From 77803587d6e15b41a66fc0ee0a87ad55ee196dfe Mon Sep 17 00:00:00 2001 -From: Thomas Woerner -Date: Wed, 3 Aug 2022 18:22:47 +0200 -Subject: [PATCH] DNSResolver: Fix use of nameservers with ports - -IPA DNS zone and forwardzone commands allow to use nameservers with ports -as "SERVER_IP port PORT_NUMBER". bind is supporting this syntax, but the -Resolver in dnspython that is used to verify the list of forwarders -(nameservers) is only allowing to have IP addresses in this list. With -dnspython version 2.20 there is a new validator in dns.resolver.BaseResolver -that ensures this. - -Refs: -- https://bind9.readthedocs.io/en/v9_18_4/reference.html#zone-statement-grammar -- https://github.com/rthalley/dnspython/blob/master/dns/resolver.py#L1094 - -ipapython/dnsutil.DNSResolver derives from dns.resolver.Resolver. The setter -for nameservers has been overloaded in the DNSResolver class to split out -the port numbers into the nameserver_ports dict { SERVER_IP: PORT_NUMBER }. -After the setter for nameservers succeeded, nameserver_ports is set. -nameserver_ports is used in the resolve() method of dns.resolver.Resolver. - -Additional tests have been added to verify that nameservers and also -nameserver_ports are properly set and also valid. - -Fixes: https://pagure.io/freeipa/issue/9158 - -Signed-off-by: Thomas Woerner -Reviewed-By: Alexander Bokovoy ---- - ipapython/dnsutil.py | 41 +++++++++++++++++++++++++ - ipatests/test_ipapython/test_dnsutil.py | 40 ++++++++++++++++++++++++ - 2 files changed, 81 insertions(+) - -diff --git a/ipapython/dnsutil.py b/ipapython/dnsutil.py -index 4baeaf8cc..58de365ab 100644 ---- a/ipapython/dnsutil.py -+++ b/ipapython/dnsutil.py -@@ -144,6 +144,47 @@ class DNSResolver(dns.resolver.Resolver): - nameservers.remove(ipv4_loopback) - self.nameservers = nameservers - -+ @dns.resolver.Resolver.nameservers.setter -+ def nameservers(self, nameservers): -+ """ -+ *nameservers*, a ``list`` of nameservers with optional ports: -+ "SERVER_IP port PORT_NUMBER". -+ -+ Overloads dns.resolver.Resolver.nameservers setter to split off ports -+ into nameserver_ports after setting nameservers successfully with the -+ setter in dns.resolver.Resolver. -+ """ -+ # Get nameserver_ports if it is already set -+ if hasattr(self, "nameserver_ports"): -+ nameserver_ports = self.nameserver_ports -+ else: -+ nameserver_ports = {} -+ -+ # Check nameserver items in list and split out converted port number -+ # into nameserver_ports: { nameserver: port } -+ if isinstance(nameservers, list): -+ _nameservers = [] -+ for nameserver in nameservers: -+ splits = nameserver.split() -+ if len(splits) == 3 and splits[1] == "port": -+ nameserver = splits[0] -+ try: -+ port = int(splits[2]) -+ if port < 0 or port > 65535: -+ raise ValueError() -+ except ValueError: -+ raise ValueError( -+ "invalid nameserver: %s is not a valid port" % -+ splits[2]) -+ nameserver_ports[nameserver] = port -+ _nameservers.append(nameserver) -+ nameservers = _nameservers -+ -+ # Call dns.resolver.Resolver.nameservers setter -+ dns.resolver.Resolver.nameservers.__set__(self, nameservers) -+ # Set nameserver_ports after successfull call to setter -+ self.nameserver_ports = nameserver_ports -+ - - class DNSZoneAlreadyExists(dns.exception.DNSException): - supp_kwargs = {'zone', 'ns'} -diff --git a/ipatests/test_ipapython/test_dnsutil.py b/ipatests/test_ipapython/test_dnsutil.py -index 5e7a46197..09463c69d 100644 ---- a/ipatests/test_ipapython/test_dnsutil.py -+++ b/ipatests/test_ipapython/test_dnsutil.py -@@ -101,3 +101,43 @@ class TestSortURI: - assert dnsutil.sort_prio_weight([h3, h2, h1]) == [h1, h2, h3] - assert dnsutil.sort_prio_weight([h3, h3, h3]) == [h3] - assert dnsutil.sort_prio_weight([h2, h2, h1, h1]) == [h1, h2] -+ -+ -+class TestDNSResolver: -+ def test_nameservers(self): -+ res = dnsutil.DNSResolver() -+ res.nameservers = ["4.4.4.4", "8.8.8.8"] -+ assert res.nameservers == ["4.4.4.4", "8.8.8.8"] -+ -+ def test_nameservers_with_ports(self): -+ res = dnsutil.DNSResolver() -+ res.nameservers = ["4.4.4.4 port 53", "8.8.8.8 port 8053"] -+ assert res.nameservers == ["4.4.4.4", "8.8.8.8"] -+ assert res.nameserver_ports == {"4.4.4.4": 53, "8.8.8.8": 8053} -+ -+ res.nameservers = ["4.4.4.4 port 53", "8.8.8.8 port 8053"] -+ assert res.nameservers == ["4.4.4.4", "8.8.8.8"] -+ assert res.nameserver_ports == {"4.4.4.4": 53, "8.8.8.8": 8053} -+ -+ def test_nameservers_with_bad_ports(self): -+ res = dnsutil.DNSResolver() -+ try: -+ res.nameservers = ["4.4.4.4 port a"] -+ except ValueError: -+ pass -+ else: -+ pytest.fail("No fail on bad port a") -+ -+ try: -+ res.nameservers = ["4.4.4.4 port -1"] -+ except ValueError: -+ pass -+ else: -+ pytest.fail("No fail on bad port -1") -+ -+ try: -+ res.nameservers = ["4.4.4.4 port 65536"] -+ except ValueError: -+ pass -+ else: -+ pytest.fail("No fail on bad port 65536") --- -2.37.1 - diff --git a/0005_Set_passwordgracelimit_to_match_global_policy_on_group_pw_policies_#6419.patch b/0005_Set_passwordgracelimit_to_match_global_policy_on_group_pw_policies_#6419.patch deleted file mode 100644 index efb82ee..0000000 --- a/0005_Set_passwordgracelimit_to_match_global_policy_on_group_pw_policies_#6419.patch +++ /dev/null @@ -1,231 +0,0 @@ -From 1aa39529cda4ab9620539dbad705cedd23c21b42 Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Thu, 18 Aug 2022 08:21:58 -0400 -Subject: [PATCH] doc: Update LDAP grace period design with default values - -New group password policies will get -1 (unlimited) on creation -by default. - -Existing group password policies will remain untouched and -those created prior will be treated as no BIND allowed. - -Fixes: https://pagure.io/freeipa/issue/9212 - -Signed-off-by: Rob Crittenden -Reviewed-By: Florence Blanc-Renaud ---- - doc/designs/ldap_grace_period.md | 17 ++++++++++++++++- - 1 file changed, 16 insertions(+), 1 deletion(-) - -diff --git a/doc/designs/ldap_grace_period.md b/doc/designs/ldap_grace_period.md -index 4b9db3424..e26aedda9 100644 ---- a/doc/designs/ldap_grace_period.md -+++ b/doc/designs/ldap_grace_period.md -@@ -51,7 +51,22 @@ The basic flow is: - - On successful password reset (by anyone) reset the user's passwordGraceUserTime to 0. - --The default value on install/upgrade will be -1 to retail existing behavior. -+Range values for passwordgracelimit are: -+ -+-1 : password grace checking is disabled -+ 0 : no grace BIND are allowed at all post-expiration -+ 1..MAXINT: the number of BIND allowed post-expiration -+ -+The default value for the global policy on install/upgrade will be -1 to -+retain existing behavior. -+ -+New group password policies will default to -1 to retain previous -+behavior. -+ -+Existing group policies with no grace limit set are updated to use -+the default unlimited value, -1. This is done because lack of value in -+LDAP is treated as 0 so any existing group policies would not allow -+post-expiration BIND so this will avoid confusion. - - The per-user attempts will not be replicated. - --- -2.37.1 - -From 45e6d49b94da78cd82eb016b3266a17a1359a087 Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Thu, 4 Aug 2022 12:04:22 -0400 -Subject: [PATCH 1/2] Set default gracelimit on group password policies to -1 - -This will retain previous behavior of unlimited LDAP BIND -post-expiration. - -Fixes: https://pagure.io/freeipa/issue/9212 - -Signed-off-by: Rob Crittenden -Reviewed-By: Florence Blanc-Renaud ---- - API.txt | 2 +- - ipaserver/plugins/pwpolicy.py | 2 ++ - ipatests/test_xmlrpc/test_pwpolicy_plugin.py | 2 ++ - 3 files changed, 5 insertions(+), 1 deletion(-) - -diff --git a/API.txt b/API.txt -index 66929b921..210bfc495 100644 ---- a/API.txt -+++ b/API.txt -@@ -4076,7 +4076,7 @@ option: Int('krbpwdlockoutduration?', cli_name='lockouttime') - option: Int('krbpwdmaxfailure?', cli_name='maxfail') - option: Int('krbpwdmindiffchars?', cli_name='minclasses') - option: Int('krbpwdminlength?', cli_name='minlength') --option: Int('passwordgracelimit?', cli_name='gracelimit', default=-1) -+option: Int('passwordgracelimit?', autofill=True, cli_name='gracelimit', default=-1) - option: Flag('raw', autofill=True, cli_name='raw', default=False) - option: Str('setattr*', cli_name='setattr') - option: Str('version?') -diff --git a/ipaserver/plugins/pwpolicy.py b/ipaserver/plugins/pwpolicy.py -index 4428aede2..f4ebffd5c 100644 ---- a/ipaserver/plugins/pwpolicy.py -+++ b/ipaserver/plugins/pwpolicy.py -@@ -408,6 +408,7 @@ class pwpolicy(LDAPObject): - minvalue=-1, - maxvalue=Int.MAX_UINT32, - default=-1, -+ autofill=True, - ), - ) - -@@ -539,6 +540,7 @@ class pwpolicy_add(LDAPCreate): - keys[-1], krbpwdpolicyreference=dn, - cospriority=options.get('cospriority') - ) -+ - return dn - - def post_callback(self, ldap, dn, entry_attrs, *keys, **options): -diff --git a/ipatests/test_xmlrpc/test_pwpolicy_plugin.py b/ipatests/test_xmlrpc/test_pwpolicy_plugin.py -index 8eee69c18..fc785223b 100644 ---- a/ipatests/test_xmlrpc/test_pwpolicy_plugin.py -+++ b/ipatests/test_xmlrpc/test_pwpolicy_plugin.py -@@ -387,6 +387,7 @@ class test_pwpolicy_mod_cospriority(Declarative): - krbpwdhistorylength=[u'10'], - krbpwdmindiffchars=[u'3'], - krbpwdminlength=[u'8'], -+ passwordgracelimit=[u'-1'], - objectclass=objectclasses.pwpolicy, - ), - summary=None, -@@ -417,6 +418,7 @@ class test_pwpolicy_mod_cospriority(Declarative): - krbpwdhistorylength=[u'10'], - krbpwdmindiffchars=[u'3'], - krbpwdminlength=[u'8'], -+ passwordgracelimit=[u'-1'], - ), - summary=None, - value=u'ipausers', --- -2.37.1 - -From de6f074538f6641fd9d84bed204a3d4d50eccbe5 Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Thu, 4 Aug 2022 12:04:41 -0400 -Subject: [PATCH 2/2] Set default on group pwpolicy with no grace limit in - upgrade - -If an existing group policy lacks a password grace limit -update it to -1 on upgrade. - -Fixes: https://pagure.io/freeipa/issue/9212 - -Signed-off-by: Rob Crittenden -Reviewed-By: Florence Blanc-Renaud ---- - .../updates/90-post_upgrade_plugins.update | 1 + - ipaserver/install/plugins/update_pwpolicy.py | 66 +++++++++++++++++++ - 2 files changed, 67 insertions(+) - -diff --git a/install/updates/90-post_upgrade_plugins.update b/install/updates/90-post_upgrade_plugins.update -index c7ec71d49..6fe91aa6c 100644 ---- a/install/updates/90-post_upgrade_plugins.update -+++ b/install/updates/90-post_upgrade_plugins.update -@@ -26,6 +26,7 @@ plugin: update_ra_cert_store - plugin: update_mapping_Guests_to_nobody - plugin: fix_kra_people_entry - plugin: update_pwpolicy -+plugin: update_pwpolicy_grace - - # last - # DNS version 1 -diff --git a/ipaserver/install/plugins/update_pwpolicy.py b/ipaserver/install/plugins/update_pwpolicy.py -index dca44ce43..4185f0343 100644 ---- a/ipaserver/install/plugins/update_pwpolicy.py -+++ b/ipaserver/install/plugins/update_pwpolicy.py -@@ -78,3 +78,69 @@ class update_pwpolicy(Updater): - return False, [] - - return False, [] -+ -+ -+@register() -+class update_pwpolicy_grace(Updater): -+ """ -+ Ensure all group policies have a grace period set. -+ """ -+ -+ def execute(self, **options): -+ ldap = self.api.Backend.ldap2 -+ -+ base_dn = DN(('cn', self.api.env.realm), ('cn', 'kerberos'), -+ self.api.env.basedn) -+ search_filter = ( -+ "(&(objectClass=krbpwdpolicy)(!(passwordgracelimit=*)))" -+ ) -+ -+ while True: -+ # Run the search in loop to avoid issues when LDAP limits are hit -+ # during update -+ -+ try: -+ (entries, truncated) = ldap.find_entries( -+ search_filter, ['objectclass'], base_dn, time_limit=0, -+ size_limit=0) -+ -+ except errors.EmptyResult: -+ logger.debug("update_pwpolicy: no policies without " -+ "passwordgracelimit set") -+ return False, [] -+ -+ except errors.ExecutionError as e: -+ logger.error("update_pwpolicy: cannot retrieve list " -+ "of policies missing passwordgracelimit: %s", e) -+ return False, [] -+ -+ logger.debug("update_pwpolicy: found %d " -+ "policies to update, truncated: %s", -+ len(entries), truncated) -+ -+ error = False -+ -+ for entry in entries: -+ # Set unlimited BIND by default -+ entry['passwordgracelimit'] = -1 -+ try: -+ ldap.update_entry(entry) -+ except (errors.EmptyModlist, errors.NotFound): -+ pass -+ except errors.ExecutionError as e: -+ logger.debug("update_pwpolicy: cannot " -+ "update policy: %s", e) -+ error = True -+ -+ if error: -+ # Exit loop to avoid infinite cycles -+ logger.error("update_pwpolicy: error(s) " -+ "detected during pwpolicy update") -+ return False, [] -+ -+ elif not truncated: -+ # All affected entries updated, exit the loop -+ logger.debug("update_pwpolicy: all policies updated") -+ return False, [] -+ -+ return False, [] --- -2.37.1 - diff --git a/freeipa-bz1948034.patch b/freeipa-bz1948034.patch deleted file mode 100644 index f36016e..0000000 --- a/freeipa-bz1948034.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 03f7731d39689ee6da7118fa4d5de01b4012c427 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Sat, 10 Apr 2021 15:40:22 +0300 -Subject: [PATCH] ipaserver/install/dns: handle SERVFAIL when checking reverse - zone - -systemd-resolved in Fedora 34+ returns SERVFAIL for reverse zone that -does not yet exist when we attempt to look it up before installation. -Assume that this is OK -- we are going to create the zone ourselves -during installation. - -Fixes: https://pagure.io/freeipa/issue/8794 - -Signed-off-by: Alexander Bokovoy ---- - ipapython/dnsutil.py | 6 ++++++ - ipaserver/install/bindinstance.py | 12 ++++++++++++ - ipaserver/install/dns.py | 12 +++++++++++- - 3 files changed, 29 insertions(+), 1 deletion(-) - -diff --git a/ipapython/dnsutil.py b/ipapython/dnsutil.py -index 63eb64dc1..67a5a5334 100644 ---- a/ipapython/dnsutil.py -+++ b/ipapython/dnsutil.py -@@ -125,6 +125,10 @@ class DNSZoneAlreadyExists(dns.exception.DNSException): - "and is handled by server(s): {ns}") - - -+class DNSNoNameservers(dns.resolver.NoNameservers): -+ pass -+ -+ - @six.python_2_unicode_compatible - class DNSName(dns.name.Name): - labels = None # make pylint happy -@@ -447,6 +451,8 @@ def check_zone_overlap(zone, raise_on_error=True): - except dns.exception.DNSException as e: - msg = ("DNS check for domain %s failed: %s." % (zone, e)) - if raise_on_error: -+ if isinstance(e, dns.resolver.NoNameservers): -+ raise DNSNoNameservers(**e.kwargs) from None - raise ValueError(msg) - else: - logger.warning('%s', msg) -diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py -index 19941cd00..f1c9e0aa2 100644 ---- a/ipaserver/install/bindinstance.py -+++ b/ipaserver/install/bindinstance.py -@@ -312,6 +312,7 @@ def read_reverse_zone(default, ip_address, allow_zone_overlap=False): - logger.error("Reverse zone %s will not be used: %s", - zone, e) - continue -+ - break - - return normalize_zone(zone) -@@ -338,6 +339,12 @@ def get_auto_reverse_zones(ip_addresses, allow_zone_overlap=False): - default_reverse, ip) - logger.debug('%s', e) - continue -+ except dnsutil.DNSNoNameservers as e: -+ # Show warning and continue in case we've got SERVFAIL -+ # because we are supposedly going to create this reverse zone -+ logger.warning('%s', str(e)) -+ continue -+ - auto_zones.append((ip, default_reverse)) - return auto_zones - -@@ -505,6 +512,11 @@ def check_reverse_zones(ip_addresses, reverse_zones, options, unattended, - else: - logger.warning('%s', msg) - continue -+ except dnsutil.DNSNoNameservers as e: -+ # Show warning and continue in case we've got SERVFAIL -+ # because we are supposedly going to create this reverse zone -+ logger.warning('%s', str(e)) -+ continue - checked_reverse_zones.append(normalize_zone(rz)) - - # check that there is reverse zone for every IP -diff --git a/ipaserver/install/dns.py b/ipaserver/install/dns.py -index b51b92bfd..cbdaf99fd 100644 ---- a/ipaserver/install/dns.py -+++ b/ipaserver/install/dns.py -@@ -151,6 +151,10 @@ def install_check(standalone, api, replica, options, hostname): - logger.warning('%s', str(e)) - else: - raise e -+ except dnsutil.DNSNoNameservers as e: -+ # Show warning and continue in case we've got SERVFAIL -+ # because we are supposedly going to create this reverse zone -+ logger.warning('%s', str(e)) - - if standalone: - print("==============================================================================") -@@ -457,7 +461,13 @@ class DNSInstallInterface(hostname.HostNameInstallInterface): - def reverse_zones(self, values): - if not self.allow_zone_overlap: - for zone in values: -- check_zone_overlap(zone) -+ try: -+ check_zone_overlap(zone) -+ except dnsutil.DNSNoNameservers as e: -+ # Show warning and continue in case we've got SERVFAIL -+ # we are supposedly going to create this reverse zone -+ logger.warning('%s', str(e)) -+ continue - - no_reverse = knob( - None, --- -2.31.1 - diff --git a/freeipa-fix-389-ds-2.0.5-upgrade.patch b/freeipa-fix-389-ds-2.0.5-upgrade.patch deleted file mode 100644 index 1aba58b..0000000 --- a/freeipa-fix-389-ds-2.0.5-upgrade.patch +++ /dev/null @@ -1,255 +0,0 @@ -From 4d4931abf0b77c431252389edb6f447b63c91d8c Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Mon, 31 May 2021 12:53:55 +0300 -Subject: [PATCH] ds: Support renaming of a replication plugin in 389-ds - -IPA topology plugin depends on the replication plugin but -389-ds cannot handle older alias querying in the plugin -configuration with 'nsslapd-plugin-depends-on-named: ..' attribute - -See https://github.com/389ds/389-ds-base/issues/4786 for details - -Fixes: https://pagure.io/freeipa/issue/8799 - -Signed-off-by: Alexander Bokovoy ---- - .../ipa-version/version-conf.ldif | 2 +- - .../topology/ipa-topology-conf.ldif | 2 +- - install/updates/10-enable-betxn.update | 2 +- - .../updates/20-enable_dirsrv_plugins.update | 4 ++-- - install/updates/20-replication.update | 2 +- - ipaserver/install/dsinstance.py | 8 ++++++- - ipaserver/install/replication.py | 24 ++++++++++++++++++- - ipaserver/install/upgradeinstance.py | 18 +++++++++++++- - .../test_ipaserver/test_topology_plugin.py | 13 +++++++++- - 9 files changed, 65 insertions(+), 10 deletions(-) - -diff --git a/daemons/ipa-slapi-plugins/ipa-version/version-conf.ldif b/daemons/ipa-slapi-plugins/ipa-version/version-conf.ldif -index 11558834c..6000868e2 100644 ---- a/daemons/ipa-slapi-plugins/ipa-version/version-conf.ldif -+++ b/daemons/ipa-slapi-plugins/ipa-version/version-conf.ldif -@@ -13,5 +13,5 @@ nsslapd-pluginversion: 1.0 - nsslapd-pluginvendor: Red Hat, Inc. - nsslapd-plugindescription: IPA Replication version plugin - nsslapd-plugin-depends-on-type: database --nsslapd-plugin-depends-on-named: Multimaster Replication Plugin -+nsslapd-plugin-depends-on-named: $REPLICATION_PLUGIN - -diff --git a/daemons/ipa-slapi-plugins/topology/ipa-topology-conf.ldif b/daemons/ipa-slapi-plugins/topology/ipa-topology-conf.ldif -index 4b3c4ce99..effa38597 100644 ---- a/daemons/ipa-slapi-plugins/topology/ipa-topology-conf.ldif -+++ b/daemons/ipa-slapi-plugins/topology/ipa-topology-conf.ldif -@@ -15,7 +15,7 @@ nsslapd-topo-plugin-shared-binddngroup: cn=replication managers,cn=sysaccounts,c - nsslapd-topo-plugin-startup-delay: 20 - nsslapd-pluginId: none - nsslapd-plugin-depends-on-named: ldbm database --nsslapd-plugin-depends-on-named: Multimaster Replication Plugin -+nsslapd-plugin-depends-on-named: $REPLICATION_PLUGIN - nsslapd-pluginVersion: 1.0 - nsslapd-pluginVendor: none - nsslapd-pluginDescription: none -diff --git a/install/updates/10-enable-betxn.update b/install/updates/10-enable-betxn.update -index 88f584cb3..1f89341c7 100644 ---- a/install/updates/10-enable-betxn.update -+++ b/install/updates/10-enable-betxn.update -@@ -18,7 +18,7 @@ only: nsslapd-pluginType: betxnpreoperation - dn: cn=MemberOf Plugin,cn=plugins,cn=config - only: nsslapd-pluginType: betxnpostoperation - --dn: cn=Multimaster Replication Plugin,cn=plugins,cn=config -+dn: cn=$REPLICATION_PLUGIN,cn=plugins,cn=config - only: nsslapd-pluginbetxn: on - - dn: cn=PAM Pass Through Auth,cn=plugins,cn=config -diff --git a/install/updates/20-enable_dirsrv_plugins.update b/install/updates/20-enable_dirsrv_plugins.update -index dc046f41b..182a8334d 100644 ---- a/install/updates/20-enable_dirsrv_plugins.update -+++ b/install/updates/20-enable_dirsrv_plugins.update -@@ -50,8 +50,8 @@ replace: nsslapd-pluginEnabled:off::on - dn: cn=Managed Entries,cn=plugins,cn=config - replace: nsslapd-pluginEnabled:off::on - --# Multimaster Replication Plugin, plugins, config --dn: cn=Multimaster Replication Plugin,cn=plugins,cn=config -+# Replication Plugin may be Multisupplier or Multimaster -+dn: cn=$REPLICATION_PLUGIN,cn=plugins,cn=config - replace: nsslapd-pluginEnabled:off::on - - # Roles Plugin, plugins, config -diff --git a/install/updates/20-replication.update b/install/updates/20-replication.update -index 34beebc10..287148ec8 100644 ---- a/install/updates/20-replication.update -+++ b/install/updates/20-replication.update -@@ -58,7 +58,7 @@ default: nsslapd-topo-plugin-shared-binddngroup: cn=replication managers,cn=sysa - default: nsslapd-topo-plugin-startup-delay: 20 - default: nsslapd-pluginId: none - default: nsslapd-plugin-depends-on-named: ldbm database --default: nsslapd-plugin-depends-on-named: Multimaster Replication Plugin -+default: nsslapd-plugin-depends-on-named: $REPLICATION_PLUGIN - default: nsslapd-pluginVersion: 1.0 - default: nsslapd-pluginVendor: none - default: nsslapd-pluginDescription: none -diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py -index 622d6a0f5..b0e012ab8 100644 ---- a/ipaserver/install/dsinstance.py -+++ b/ipaserver/install/dsinstance.py -@@ -571,6 +571,12 @@ class DsInstance(service.Service): - inst.setup_ldapi() - inst.open() - -+ def get_entry(dn, attrs): -+ return inst.getEntry(dn, attrlist=attrs) -+ -+ self.sub_dict['REPLICATION_PLUGIN'] = ( -+ replication.get_replication_plugin_name(get_entry)) -+ - try: - ipadomain = IpaDomain(inst, dn=self.suffix.ldap_text()) - ipadomain.create(properties={ -@@ -735,7 +741,7 @@ class DsInstance(service.Service): - self._ldap_mod("pw-logging-conf.ldif") - - def __config_version_module(self): -- self._ldap_mod("version-conf.ldif") -+ self._ldap_mod("version-conf.ldif", self.sub_dict) - - def __config_uuid_module(self): - self._ldap_mod("uuid-conf.ldif") -diff --git a/ipaserver/install/replication.py b/ipaserver/install/replication.py -index 5a3e5e565..8fb4fd414 100644 ---- a/ipaserver/install/replication.py -+++ b/ipaserver/install/replication.py -@@ -232,6 +232,23 @@ def get_ds_version(conn): - return vendor_version - - -+def get_replication_plugin_name(dirsrv_get_entry): -+ # Support renaming of a replication plugin in 389-ds -+ # IPA topology plugin depends on the replication plugin but -+ # 389-ds cannot handle older alias querying in the plugin -+ # configuration with 'nsslapd-plugin-depends-on-named: ..' attribute -+ # -+ # dirsrv_get_entry: function (dn, attrs) -> str -+ # returns entry dictionary -+ try: -+ entry = dirsrv_get_entry( -+ 'cn=Multisupplier Replication Plugin,cn=plugins,cn=config', -+ ['cn']) -+ return str(entry['cn'], encoding='utf-8') -+ except Exception: -+ return 'Multimaster Replication Plugin' -+ -+ - class ReplicationManager: - """Manage replication agreements - -@@ -737,8 +754,13 @@ class ReplicationManager: - mtent = self.get_mapping_tree_entry() - dn = mtent.dn - -+ def get_entry(dn, attrs): -+ return self.conn.get_entry(DN(dn), attrs) -+ -+ replication_plugin_name = get_replication_plugin_name(get_entry) -+ - plgent = self.conn.get_entry( -- DN(('cn', 'Multimaster Replication Plugin'), ('cn', 'plugins'), -+ DN(('cn', replication_plugin_name), ('cn', 'plugins'), - ('cn', 'config')), - ['nsslapd-pluginPath']) - path = plgent.single_value.get('nsslapd-pluginPath') -diff --git a/ipaserver/install/upgradeinstance.py b/ipaserver/install/upgradeinstance.py -index a239dd035..581742d6f 100644 ---- a/ipaserver/install/upgradeinstance.py -+++ b/ipaserver/install/upgradeinstance.py -@@ -40,6 +40,7 @@ logger = logging.getLogger(__name__) - - DSE = 'dse.ldif' - COMPAT_DN = "cn=Schema Compatibility,cn=plugins,cn=config" -+REPL_PLUGIN_DN_TEMPLATE = "cn=Multi%s Replication Plugin,cn=plugins,cn=config" - - - class GetEntryFromLDIF(ldif.LDIFParser): -@@ -97,6 +98,7 @@ class IPAUpgrade(service.Service): - self.modified = False - self.serverid = serverid - self.schema_files = schema_files -+ self.sub_dict = dict() - - def __start(self): - srv = services.service(self.service_name, api) -@@ -170,6 +172,20 @@ class IPAUpgrade(service.Service): - else: - self.backup_state('nsslapd-global-backend-lock', global_lock) - -+ # update self.sub_dict with the replication plugin name -+ # It may be different depending on 389-ds version -+ with open(self.filename, "r") as in_file: -+ parser = GetEntryFromLDIF(in_file, entries_dn=[]) -+ parser.parse() -+ -+ results = parser.get_results() -+ -+ dn = REPL_PLUGIN_DN_TEMPLATE % "supplier" -+ if dn not in results: -+ dn = REPL_PLUGIN_DN_TEMPLATE % "master" -+ -+ self.sub_dict['REPLICATION_PLUGIN'] = results[dn].get('cn') -+ - with open(self.filename, "r") as in_file: - parser = GetEntryFromLDIF(in_file, entries_dn=[COMPAT_DN]) - parser.parse() -@@ -284,7 +300,7 @@ class IPAUpgrade(service.Service): - - def __upgrade(self): - try: -- ld = ldapupdate.LDAPUpdate(api=self.api) -+ ld = ldapupdate.LDAPUpdate(api=self.api, sub_dict=self.sub_dict) - if len(self.files) == 0: - self.files = ld.get_all_files(ldapupdate.UPDATES_DIR) - self.modified = (ld.update(self.files) or self.modified) -diff --git a/ipatests/test_ipaserver/test_topology_plugin.py b/ipatests/test_ipaserver/test_topology_plugin.py -index ca68a8905..be24ac5c1 100644 ---- a/ipatests/test_ipaserver/test_topology_plugin.py -+++ b/ipatests/test_ipaserver/test_topology_plugin.py -@@ -10,6 +10,8 @@ from ipapython.dn import DN - import pytest - - -+REPL_PLUGIN_NAME_TEMPLATE = 'Multi%s Replication Plugin' -+ - @pytest.mark.tier1 - class TestTopologyPlugin: - """ -@@ -35,12 +37,13 @@ class TestTopologyPlugin: - @pytest.mark.skipif(os.path.isfile(pwfile) is False, - reason="You did not provide a .dmpw file with the DM password") - def test_topologyplugin(self): -+ supplier = REPL_PLUGIN_NAME_TEMPLATE % 'supplier' - pluginattrs = { - u'nsslapd-pluginPath': [u'libtopology'], - u'nsslapd-pluginVendor': [u'freeipa'], - u'cn': [u'IPA Topology Configuration'], - u'nsslapd-plugin-depends-on-named': -- [u'Multimaster Replication Plugin', u'ldbm database'], -+ [supplier, u'ldbm database'], - u'nsslapd-topo-plugin-shared-replica-root': [u'dc=example,dc=com'], - u'nsslapd-pluginVersion': [u'1.0'], - u'nsslapd-topo-plugin-shared-config-base': -@@ -72,5 +75,13 @@ class TestTopologyPlugin: - bind_pw=dm_password) - entry = self.conn.get_entry(topoplugindn) - assert(set(entry.keys()) == set(pluginattrs.keys())) -+ -+ # Handle different names for replication plugin -+ key = 'nsslapd-plugin-depends-on-named' -+ plugin_dependencies = entry[key] -+ if supplier not in plugin_dependencies: -+ mm = REPL_PLUGIN_NAME_TEMPLATE % 'master' -+ pluginattrs[key] = [mm, 'ldbm database'] -+ - for i in checkvalues: - assert(set(pluginattrs[i]) == set(entry[i])) --- -2.31.1 - diff --git a/freeipa-fix-missing-creds.patch b/freeipa-fix-missing-creds.patch deleted file mode 100644 index 426c922..0000000 --- a/freeipa-fix-missing-creds.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 5238651da06547bb004de2434ae7d357422ba735 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Fri, 4 Jun 2021 15:35:58 +0300 -Subject: [PATCH] get_credentials: return ValueError for missing creds - -Related: https://pagure.io/freeipa/issue/8873 - -Signed-off-by: Alexander Bokovoy ---- - ipalib/krb_utils.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ipalib/krb_utils.py b/ipalib/krb_utils.py -index 1002bbaa6..21078ef3e 100644 ---- a/ipalib/krb_utils.py -+++ b/ipalib/krb_utils.py -@@ -153,7 +153,7 @@ def get_credentials(name=None, ccache_name=None): - return gssapi.Credentials(usage='initiate', name=name, store=store) - except gssapi.exceptions.GSSError as e: - if e.min_code in ( # pylint: disable=no-member -- KRB5_FCC_NOFILE, GSSPROXY_KRB5_FCC_NOFILE, -+ KRB5_FCC_NOFILE, GSSPROXY_KRB5_FCC_NOFILE, KRB5_CC_NOTFOUND, - ): - raise ValueError('"%s", ccache="%s"' % (e, ccache_name)) - raise --- -2.31.1 - diff --git a/freeipa-harden-pac-2.patch b/freeipa-harden-pac-2.patch deleted file mode 100644 index abfc547..0000000 --- a/freeipa-harden-pac-2.patch +++ /dev/null @@ -1,222 +0,0 @@ -From fe59e6a0b06926a3d71c6b6f361714d1422d5b0f Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Thu, 11 Nov 2021 09:58:09 +0200 -Subject: [PATCH 1/2] ipa-kdb: honor SID from the host or service entry - -If the SID was explicitly set for the host or service entry, honor it -when issuing PAC. For normal services and hosts we don't allocate -individual SIDs but for cifs/... principals on domain members we do as -they need to login to Samba domain controller. - -Related: https://pagure.io/freeipa/issue/9031 - -Signed-off-by: Alexander Bokovoy ---- - daemons/ipa-kdb/ipa_kdb_mspac.c | 46 ++++++++++++++++++++------------- - 1 file changed, 28 insertions(+), 18 deletions(-) - -diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c -index 0e0ee3616..6f272f9fe 100644 ---- a/daemons/ipa-kdb/ipa_kdb_mspac.c -+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c -@@ -653,6 +653,28 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx, - * clear it after detecting the changes */ - info3->base.acct_flags = ACB_USE_AES_KEYS; - -+ ret = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry, -+ "ipaNTSecurityIdentifier", &strres); -+ if (ret) { -+ /* SID is mandatory for all but host/services */ -+ if (!(is_host || is_service)) { -+ return ret; -+ } -+ info3->base.rid = 0; -+ } else { -+ ret = ipadb_string_to_sid(strres, &sid); -+ free(strres); -+ if (ret) { -+ return ret; -+ } -+ ret = sid_split_rid(&sid, &info3->base.rid); -+ if (ret) { -+ return ret; -+ } -+ } -+ -+ /* If SID was present prefer using it even for hosts and services -+ * but we still need to set the account flags correctly */ - if ((is_host || is_service)) { - /* it is either host or service, so get the hostname first */ - char *sep = strchr(info3->base.account_name.string, '/'); -@@ -661,29 +683,17 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx, - sep ? sep + 1 : info3->base.account_name.string); - if (is_master) { - /* Well known RID of domain controllers group */ -- info3->base.rid = 516; -+ if (info3->base.rid == 0) { -+ info3->base.rid = 516; -+ } - info3->base.acct_flags |= ACB_SVRTRUST; - } else { - /* Well known RID of domain computers group */ -- info3->base.rid = 515; -+ if (info3->base.rid == 0) { -+ info3->base.rid = 515; -+ } - info3->base.acct_flags |= ACB_WSTRUST; - } -- } else { -- ret = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry, -- "ipaNTSecurityIdentifier", &strres); -- if (ret) { -- /* SID is mandatory */ -- return ret; -- } -- ret = ipadb_string_to_sid(strres, &sid); -- free(strres); -- if (ret) { -- return ret; -- } -- ret = sid_split_rid(&sid, &info3->base.rid); -- if (ret) { -- return ret; -- } - } - - ret = ipadb_ldap_deref_results(ipactx->lcontext, lentry, &deref_results); --- -2.33.1 - - -From 21af43550aa0a31e1ec5240578bd64fcbdd4ee24 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Thu, 11 Nov 2021 10:16:47 +0200 -Subject: [PATCH 2/2] ipa-kdb: validate domain SID in incoming PAC for trusted - domains for S4U - -Previously, ipadb_check_logon_info() was called only for cross-realm -case. Now we call it for both in-realm and cross-realm cases. In case of -the S4U2Proxy, we would be passed a PAC of the original caller which -might be a principal from the trusted realm. We cannot validate that PAC -against our local client DB entry because this is the proxy entry which -is guaranteed to have different SID. - -In such case, validate the SID of the domain in PAC against our realm -and any trusted doman but skip an additional check of the DB entry in -the S4U2Proxy case. - -Related: https://pagure.io/freeipa/issue/9031 - -Signed-off-by: Alexander Bokovoy ---- - daemons/ipa-kdb/ipa_kdb_mspac.c | 54 ++++++++++++++++++++++++++------- - 1 file changed, 43 insertions(+), 11 deletions(-) - -diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c -index 6f272f9fe..6f7d1ac15 100644 ---- a/daemons/ipa-kdb/ipa_kdb_mspac.c -+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c -@@ -1637,11 +1637,13 @@ static void filter_logon_info_log_message_rid(struct dom_sid *sid, uint32_t rid) - static krb5_error_code check_logon_info_consistent(krb5_context context, - TALLOC_CTX *memctx, - krb5_const_principal client_princ, -+ krb5_boolean is_s4u, - struct PAC_LOGON_INFO_CTR *info) - { - krb5_error_code kerr = 0; - struct ipadb_context *ipactx; - bool result; -+ bool is_from_trusted_domain = false; - krb5_db_entry *client_actual = NULL; - struct ipadb_e_data *ied = NULL; - int flags = 0; -@@ -1671,14 +1673,36 @@ static krb5_error_code check_logon_info_consistent(krb5_context context, - result = dom_sid_check(&ipactx->mspac->domsid, - info->info->info3.base.domain_sid, true); - if (!result) { -- /* memctx is freed by the caller */ -- char *sid = dom_sid_string(memctx, info->info->info3.base.domain_sid); -- char *dom = dom_sid_string(memctx, &ipactx->mspac->domsid); -- krb5_klog_syslog(LOG_ERR, "PAC issue: PAC record claims domain SID different " -- "to local domain SID: local [%s], PAC [%s]", -- dom ? dom : "", -- sid ? sid : ""); -- return KRB5KDC_ERR_POLICY; -+ /* In S4U case we might be dealing with the PAC issued by the trusted domain */ -+ if (is_s4u && (ipactx->mspac->trusts != NULL)) { -+ /* Iterate through list of trusts and check if this SID belongs to -+ * one of the domains we trust */ -+ for(int i = 0 ; i < ipactx->mspac->num_trusts ; i++) { -+ result = dom_sid_check(&ipactx->mspac->trusts[i].domsid, -+ info->info->info3.base.domain_sid, true); -+ if (result) { -+ is_from_trusted_domain = true; -+ break; -+ } -+ } -+ } -+ -+ if (!result) { -+ /* memctx is freed by the caller */ -+ char *sid = dom_sid_string(memctx, info->info->info3.base.domain_sid); -+ char *dom = dom_sid_string(memctx, &ipactx->mspac->domsid); -+ krb5_klog_syslog(LOG_ERR, "PAC issue: PAC record claims domain SID different " -+ "to local domain SID or any trusted domain SID: " -+ "local [%s], PAC [%s]", -+ dom ? dom : "", -+ sid ? sid : ""); -+ return KRB5KDC_ERR_POLICY; -+ } -+ } -+ -+ if (is_s4u && is_from_trusted_domain) { -+ /* If the PAC belongs to a user from the trusted domain, we cannot compare SIDs */ -+ return 0; - } - - kerr = ipadb_get_principal(context, client_princ, flags, &client_actual); -@@ -1703,6 +1727,7 @@ static krb5_error_code check_logon_info_consistent(krb5_context context, - goto done; - } - -+ - kerr = ipadb_get_sid_from_pac(memctx, info->info, &client_sid); - if (kerr) { - goto done; -@@ -1956,6 +1981,7 @@ krb5_error_code filter_logon_info(krb5_context context, - static krb5_error_code ipadb_check_logon_info(krb5_context context, - krb5_const_principal client_princ, - krb5_boolean is_cross_realm, -+ krb5_boolean is_s4u, - krb5_data *pac_blob, - struct dom_sid *requester_sid) - { -@@ -1999,8 +2025,11 @@ static krb5_error_code ipadb_check_logon_info(krb5_context context, - - if (!is_cross_realm) { - /* For local realm case we need to check whether the PAC is for our user -- * but we don't need to process further */ -- kerr = check_logon_info_consistent(context, tmpctx, client_princ, &info); -+ * but we don't need to process further. In S4U2Proxy case when the client -+ * is ours but operates on behalf of the cross-realm principal, we will -+ * search through the trusted domains but otherwise skip the exact SID check -+ * as we are not responsible for the principal from the trusted domain */ -+ kerr = check_logon_info_consistent(context, tmpctx, client_princ, is_s4u, &info); - goto done; - } - -@@ -2251,7 +2280,10 @@ static krb5_error_code ipadb_verify_pac(krb5_context context, - #endif - - kerr = ipadb_check_logon_info(context, -- client_princ, is_cross_realm, &pac_blob, -+ client_princ, -+ is_cross_realm, -+ (flags & KRB5_KDB_FLAGS_S4U), -+ &pac_blob, - requester_sid); - if (kerr != 0) { - goto done; --- -2.33.1 - diff --git a/freeipa-harden-pac.patch b/freeipa-harden-pac.patch deleted file mode 100644 index 860ac68..0000000 --- a/freeipa-harden-pac.patch +++ /dev/null @@ -1,4223 +0,0 @@ -From 929426c6d0a78cea84ccacb1629a5f8b74019ee2 Mon Sep 17 00:00:00 2001 -From: Florence Blanc-Renaud -Date: Mon, 27 Sep 2021 17:07:13 +0200 -Subject: [PATCH 01/26] Design: Integrate SID configuration into base IPA - installers - -Add design doc for the feature. - -Related: https://pagure.io/freeipa/issue/8995 -Signed-off-by: Florence Blanc-Renaud -Reviewed-By: Alexander Bokovoy -Reviewed-By: Rob Crittenden -(cherry picked from commit bacddb8288a284385e2864127a451b79c3469c93) ---- - doc/designs/adtrust/sidconfig.md | 301 +++++++++++++++++++++++++++++++ - doc/designs/index.rst | 1 + - 2 files changed, 302 insertions(+) - create mode 100644 doc/designs/adtrust/sidconfig.md - -diff --git a/doc/designs/adtrust/sidconfig.md b/doc/designs/adtrust/sidconfig.md -new file mode 100644 -index 000000000..f65d10529 ---- /dev/null -+++ b/doc/designs/adtrust/sidconfig.md -@@ -0,0 +1,301 @@ -+# Integrate SID configuration into base IPA installers -+ -+## Overview -+ -+FreeIPA is able to issue Kerberos tickets with PAC data when it is configured -+for trust. The goal of this feature is to allow PAC generation in the -+general use case, even without trust, as it is a first step towards -+IPA-IPA trust. -+ -+Reference: https://pagure.io/freeipa/issue/8995 -+ -+In order to generate PAC data for a kerberos principal, IPA needs to assign -+a SID to the users and groups. IPA installers (`ipa-server-install`, -+`ipa-replica-install`) must handle the configuration related to SID: -+- assign a NetBIOS name to the server -+- assign a domain SID to the IPA domain -+- configure the local id range with primary RID base and secondary RID base -+- enable the sidgen plugin on 389ds server -+ -+The code handling these steps is already available in ipa-adtrust-install -+and needs to be moved to the general installers. -+ -+## Use Cases -+ -+### Fresh install -+As administrator, I want to deploy an IPA topology that automatically -+assigns SIDs to users and groups and issues kerberos tickets with PAC data, -+without the need to configure IPA for trust. -+ -+If I later decide to configure IPA for trust, I can still run the command -+`ipa-adtrust-install`. -+ -+### Existing installation, no trust -+ -+As IPA administrator, I am managing an existing IPA installation without any -+trust. I want to update IPA and have the choice of enabling (or not) the -+generation of SIDs and PAC data. -+ -+If I choose to enable PAC data, I just need to run a command that requires -+an admin kerberos ticket. The command handles the SID-related configuration -+and prompts me whether I want to immediately generate SIDs for -+existing users/groups or run that task later. -+ -+### Existing installation, trust configured -+ -+In this topology with trust configured (the command `ipa-adtrust-install` has -+been executed), IPA is already able to issue Kerberos tickets with PAC data. -+Update does not modify the configuration. -+ -+### Mixed topology -+ -+As IPA administrator, I am managing an existing server setup without trust and -+without PAC data. I want to add a replica into my existing topology and -+automatically enable PAC data generation, without the need to configure IPA -+for trust. -+ -+## How to Use -+ -+### Fresh installation -+Run `ipa-server-install`, with the ability to define: -+- NetBIOS Name: if not specified, the default value is generated from -+the IPA domain name (transform the left-most label into uppercase, keep only -+ascii characters, digits and dashes). -+- Primary RID base (default if not set: 1000) -+- Secondary RID base (default if not set: 1000000) -+ -+On a replica: run `ipa-replica-install`, with the ability to define the same -+parameters as `ipa-server-install`, plus the following parameter: -+- Run SIDgen task immediately: yes/no (default=no) -+ -+If conflicting values are specified in `ipa-replica-install`, the installer -+must warn that existing values will be overwritten (same message as when -+`ipa-adtrust-install` is run multiple times with conflicting values). -+ -+### Upgrade -+ -+- Run `dnf update *ipa-server`. The upgrade doesn't configure SID-related -+options and doesn't enable PAC generation. -+- Obtain a ticket for the admin (or any member of the admins group). -+- Run the new command allowing to setup the SID-related configuration. -+- Run the existing command to modify base RID and secondary base RID: -+``` -+ipa idrange-mod --rid-base INT --secondary-rid-base INT RANGENAME -+``` -+ -+### Mixed topology -+ -+The existing server is not setup for PAC data generation. The future replica -+is installed with the latest packages, containing the updated installers. -+ -+Run `ipa-replica-install`, with the ability to define: -+- NetBIOS Name: if not specified, the default value is generated from -+the IPA domain name (transform the left-most label into uppercase, keep only -+ascii characters, digits and dashes). -+- Primary RID base (default if not set: 1000) -+- Secondary RID base (default if not set: 1000000) -+- Run SIDgen task immediately: yes/no (default=no) -+ -+ -+## Design -+ -+Installers and SID-related options: -+- the options `--add-sids`, `--netbios-name`, `--rid-base` and -+`--secondary-rid-base` are moved from ADTrustInstallInterface to a separate -+new InstallInterface: SIDInstallInterface. -+- ADTrustInstallInterface now inherits from SIDInstallInterface. -+- `adtrustinstance.ADTRUSTInstance.__init__` now accepts an additional -+parameter: `fulltrust`. When set to True, the class ADTRUSTInstance configures -+the trust as usual. When set to False, only the SID-related part is executed. -+- `ipa-server-install` and `ipa-replica-install` now always call -+`adtrust.install_check` and `adtrust.install`, but the method is using the -+provided options (especially `options.setup_adtrust`) to know if full -+configuration is required or only the SID-related part. -+ -+The `ipa-adtrust-install` code is already written in order to be -+idempotent (can be called multiple times, even with different values), and -+this property is of great value for this feature. It allows to keep -+the changes as minimal as possible to the existing installers, and -+call `ipa-adtrust-install` even if the SID-part is already setup. -+ -+New command to enable SID generation after an upgrade: -+as we don't want to automatically enable SID generation during an upgrade, -+a new command is provided in order to manually enable the feature. The command -+only requires an admin ticket (no need to be root) and relies on the admin -+framework. -+ -+The command uses a mechanism similar to server_conncheck: -+- the user must have Replication Administrators privilege -+- the user launches an ipa command communicating with IPA framework -+- the admin framework uses Dbus to get access a DBus interface that -+launches a command through oddjob, allowing the command to run as root. -+The oddjob command is a wrapper around `adtrustinstance.ADTRUSTInstance`. -+ -+## Implementation -+ -+- Dependencies: no additional dependency on ipa-server package -+- Backup and Restore: no new file to backup -+ -+## Feature Management -+ -+### UI -+ -+No new UI for server/replica installation. -+ -+`IPA server / ID ranges` tab is already available and displays Primary and -+Secondary RID base. -+ -+`IPA Server / Trusts / Global Trust Configuration` tab already displays the -+NetBIOS Name and Security Identifier. -+ -+These values can also be added in the `IPA Server / Configuration` tab. -+ -+The User View displays SMB attributes if they exist and could be enhanced -+with a note if the user entry does not have any SID, pointing the admin -+to a procedure in order to generate the missing SIDs. -+ -+### CLI -+ -+| Command | Options | -+| --- | ----- | -+| ipa-server-install | [--netbios-name=NETBIOS_NAME] [--rid-base=RID_BASE] [--secondary-rid-base=SECONDARY_RID_BASE] | -+| ipa-replica-install | [--netbios-name=NETBIOS_NAME] [--rid-base=RID_BASE] [--secondary-rid-base=SECONDARY_RID_BASE] [--add-sids] | -+| ipa config-mod | --enable-sid [--add-sids] [--netbios-name=NETBIOS_NAME] | -+ -+#### `ipa config-mod --enable-sid` details: -+ -+The `--enable-sid` option turns the feature on, and `--add-sids` triggers -+the SIDgen task in order to immediately generate SID for existing users or -+groups. -+ -+`--add-sids` requires the `--enable-sid`option. -+ -+The `--netbios-name` option specifies the NetBIOS Name and is optional. If -+not provided, the NetBIOS Name is generated from the leading part of the -+DNS name. -+ -+`--netbios-name` requires the `--enable-sid` option. -+ -+ -+### Configuration -+ -+When the feature is turned on, it is possible to modify the primary and -+secondary RID bases for the local id range with the existing -+`ipa idrange-mod` command. -+ -+The NetBIOS Name can be overwritten (with warning) when `ipa-adtrust-install` -+is run. -+ -+## Upgrade -+ -+The upgrade does not turn on the feature. If the admin wants to enable -+SID generation, he needs to update the packages and run the new command -+`ipa config-mod --enable-sid`. -+ -+ -+## Test plan -+ -+Note: PRCI currently doesn't have the ability to test upgrade. -+ -+Scenarios to be tested: fresh install, test PAC generation -+- Add active user testuser (reinitialize password) -+- On IPA server run `kinit -k` to get a ticket for `host/fqdn@REALM` -+- On IPA server run `/usr/libexec/ipa/ipa-print-pac ticket testuser` and -+ensure that PAC data is properly displayed. -+- Same test on IPA replica -+ -+Tests outside of PRCI: -+- Existing topology without trust, update one server, ensure SID generation -+hasn't been automatically enabled -+- Existing topology without trust, update one server, manually enable SID -+generation with the new command -+- Existing topology without trust, insert a new replica, ensure SID generation -+has been automatically enabled -+- Existing topology with trust, update one server, ensure SID generation is -+still working -+- Existing topology with trust, insert a new replica, ensure SID generation -+is still working -+- Ensure that `ipa-adtrust-install` is still working with the previous -+scenarios. -+ -+## Troubleshooting and debugging -+ -+When the feature is turned on (whatever the path, either through fresh -+server installation, fresh replica installation, or with the new command), the -+following LDAP entries are expected: -+ -+- `cn=ad,cn=trusts,dc=ipa,dc=test` which is a simple `nsContainer` -+- `cn=ad,cn=etc,dc=ipa,dc=test` which is a simple `nsContainer` -+- `cn=ipa.test,cn=ad,cn=etc,dc=ipa,dc=test`: must define the NetBIOS Name in -+`ipaNTFlatName`, the SID in `ipaNTSecurityIdentifier` and the default SMB -+group in `ipaNTFallbackPrimaryGroup` -+- `cn=Default SMB Group,cn=groups,cn=accounts,dc=ipa,dc=test`: must define -+a SID belonging to the IPA domain SID in `ipaNTSecurityIdentifier` -+ -+(replace ipa.test with the actual domain name and dc=ipa,dc=test with the -+actual base DN). -+ -+The admin user must have a SID ending with -500 (well-known SID for the -+domain administrator): -+``` -+# ipa user-show admin --all | grep ipantsecurityidentifier -+ ipantsecurityidentifier: S-1-5-21-2633809701-976279387-419745629-500 -+``` -+ -+The admins group must have a SID ending with -512 (well-known SID for domain -+administrators group): -+``` -+# ipa group-show admins --all | grep ipantsecurityidentifier -+ ipantsecurityidentifier: S-1-5-21-2633809701-976279387-419745629-512 -+``` -+ -+The sidgen plugin must be enabled in /etc/dirsrv/slapd-IPA-TEST/dse.ldif: -+``` -+dn: cn=IPA SIDGEN,cn=plugins,cn=config -+cn: IPA SIDGEN -+nsslapd-basedn: dc=ipa,dc=test -+nsslapd-plugin-depends-on-type: database -+nsslapd-pluginDescription: Add a SID to newly added or modified objects with u -+ id pr gid numbers -+nsslapd-pluginEnabled: on -+nsslapd-pluginId: IPA SIDGEN postop plugin -+nsslapd-pluginInitfunc: ipa_sidgen_init -+nsslapd-pluginPath: libipa_sidgen -+nsslapd-pluginType: postoperation -+nsslapd-pluginVendor: FreeIPA project -+nsslapd-pluginVersion: FreeIPA/1.0 -+objectClass: top -+objectClass: nsSlapdPlugin -+objectClass: extensibleObject -+ -+``` -+ -+If the PAC data is not generated for a user, ensure that the user contains a -+SID in its `ipantsecurityidentifier` attribute. If the SID is missing, run -+the SIDgen task in order to generate SID for existing users and groups: -+- Find ipa base DN with: `grep basedn /etc/ipa/default.conf | cut -d= -f2-` -+- Copy `/usr/share/ipa/ipa-sidgen-task-run.ldif` to -+`/tmp/ipa-sidgen-task-run.ldif` -+- Edit the copy `/tmp/ipa-sidgen-task-run.ldif` and replace $SUFFIX with -+IPA base DN -+- As root, launch the task (replace IPA-TEST with the proper value): -+`ldapmodify -H ldapi://%2Frun%2Fslapd-IPA-TEST.socket -f /tmp/ipa-sidgen-task-run.ldif` -+ -+In order to check if the PAC data gets added to the user ticket, on a server: -+``` -+# kinit -k -+# /usr/libexec/ipa/ipa-print-pac ticket USERNAME -+``` -+ -+If the PAC data is properly added, the `ipa-print-pac` command displays: -+``` -+# /usr/libexec/ipa/ipa-print-pac ticket testuser -+Password: -+Acquired credentials for testuser -+PAC_DATA: struct PAC_DATA -+ num_buffers : 0x00000005 (5) -+ version : 0x00000000 (0) -+ buffers: ARRAY(5) -+ buffers: struct PAC_BUFFER -+... -+``` -\ No newline at end of file -diff --git a/doc/designs/index.rst b/doc/designs/index.rst -index 6dd0edff3..5d346f8da 100644 ---- a/doc/designs/index.rst -+++ b/doc/designs/index.rst -@@ -10,6 +10,7 @@ FreeIPA design documentation - adtrust/admin-ipa-as-trusted-user.md - adtrust/sudorules-with-ad-objects.md - adtrust/auto-private-groups.md -+ adtrust/sidconfig.md - krb-ticket-policy.md - extdom-plugin-protocol.md - expiring-password-notification.md --- -2.33.1 - - -From e951f257074b224533a304d54400e83dd17c2c5d Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Wed, 13 Oct 2021 17:54:12 -0400 -Subject: [PATCH 02/26] On redhat-based platforms rely on authselect to enable - sudo - -The default platform task enable_sssd_sudo() writes directly -to nsswitch.conf to enable sudo. This isn't necessary to do on -systems with authselect where we already pass in with-sudo as a -profile option. - -Override the default function with does a direct write with a no-op. - -https://pagure.io/freeipa/issue/8755 - -Signed-off-by: Rob Crittenden -Reviewed-By: Alexander Bokovoy -(cherry picked from commit 5856f107335cf6ab4e6e960a53c52b2f549fce35) ---- - ipaplatform/redhat/tasks.py | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/ipaplatform/redhat/tasks.py b/ipaplatform/redhat/tasks.py -index 4b0209f5d..2271cd20a 100644 ---- a/ipaplatform/redhat/tasks.py -+++ b/ipaplatform/redhat/tasks.py -@@ -756,6 +756,9 @@ class RedHatTaskNamespace(BaseTaskNamespace): - "{}.module".format(name)) - for name, _module, _disabled in PKCS11_MODULES) - -+ def enable_sssd_sudo(self, _fstore): -+ """sudo enablement is handled by authselect""" -+ - def enable_ldap_automount(self, statestore): - """ - Point automount to ldap in nsswitch.conf. --- -2.33.1 - - -From 345232a602920c8701aaf4a8b4b540ec9342e17a Mon Sep 17 00:00:00 2001 -From: Stanislav Levin -Date: Tue, 19 Oct 2021 17:19:03 +0300 -Subject: [PATCH 03/26] ipatests: TestMultipleExternalCA: Create tempfiles on - remote host - -Previously, `test_master_install_ca1` and `test_master_install_ca2` -attempt to create tempdirs on local host and later write some -content into the returned paths on remote host. This fails if -a remote host is a local one. - -The existent `create_temp_file` function has been extended to -support `suffix` option of `mktemp`. - -Fixes: https://pagure.io/freeipa/issue/9013 -Signed-off-by: Stanislav Levin -Reviewed-By: Mohammad Rizwan -Reviewed-By: Rob Crittenden -(cherry picked from commit 18456e71a1be7b11b131afcbb675286117453e76) ---- - ipatests/pytest_ipa/integration/tasks.py | 6 ++++-- - ipatests/test_integration/test_external_ca.py | 17 ++++++++++++----- - 2 files changed, 16 insertions(+), 7 deletions(-) - -diff --git a/ipatests/pytest_ipa/integration/tasks.py b/ipatests/pytest_ipa/integration/tasks.py -index b01b52f5a..58f84735f 100755 ---- a/ipatests/pytest_ipa/integration/tasks.py -+++ b/ipatests/pytest_ipa/integration/tasks.py -@@ -2093,13 +2093,15 @@ def ldapsearch_dm(host, base, ldap_args, scope='sub', **kwargs): - return host.run_command(args, **kwargs) - - --def create_temp_file(host, directory=None, create_file=True): -- """Creates temporary file using mktemp.""" -+def create_temp_file(host, directory=None, suffix=None, create_file=True): -+ """Creates temporary file using mktemp. See `man 1 mktemp`.""" - cmd = ['mktemp'] - if create_file is False: - cmd += ['--dry-run'] - if directory is not None: - cmd += ['-p', directory] -+ if suffix is not None: -+ cmd.extend(["--suffix", suffix]) - return host.run_command(cmd).stdout_text.strip() - - -diff --git a/ipatests/test_integration/test_external_ca.py b/ipatests/test_integration/test_external_ca.py -index d48d73deb..bdb7fb65e 100644 ---- a/ipatests/test_integration/test_external_ca.py -+++ b/ipatests/test_integration/test_external_ca.py -@@ -20,7 +20,6 @@ from __future__ import absolute_import - import os - import re - import time --import tempfile - - from cryptography import x509 - from cryptography.hazmat.backends import default_backend -@@ -464,8 +463,12 @@ class TestMultipleExternalCA(IntegrationTest): - def test_master_install_ca1(self): - install_server_external_ca_step1(self.master) - # Sign CA, transport it to the host and get ipa a root ca paths. -- root_ca_fname1 = tempfile.mkdtemp(suffix='root_ca.crt', dir=paths.TMP) -- ipa_ca_fname1 = tempfile.mkdtemp(suffix='ipa_ca.crt', dir=paths.TMP) -+ root_ca_fname1 = tasks.create_temp_file( -+ self.master, directory=paths.TMP, suffix="root_ca.crt" -+ ) -+ ipa_ca_fname1 = tasks.create_temp_file( -+ self.master, directory=paths.TMP, suffix="ipa_ca.crt" -+ ) - - ipa_csr = self.master.get_file_contents(paths.ROOT_IPA_CSR) - -@@ -485,8 +488,12 @@ class TestMultipleExternalCA(IntegrationTest): - assert "CN=RootCA1" in result.stdout_text - - def test_master_install_ca2(self): -- root_ca_fname2 = tempfile.mkdtemp(suffix='root_ca.crt', dir=paths.TMP) -- ipa_ca_fname2 = tempfile.mkdtemp(suffix='ipa_ca.crt', dir=paths.TMP) -+ root_ca_fname2 = tasks.create_temp_file( -+ self.master, directory=paths.TMP, suffix="root_ca.crt" -+ ) -+ ipa_ca_fname2 = tasks.create_temp_file( -+ self.master, directory=paths.TMP, suffix="ipa_ca.crt" -+ ) - - self.master.run_command([ - paths.IPA_CACERT_MANAGE, 'renew', '--external-ca']) --- -2.33.1 - - -From d1b6bfd9f1000ef9f0b3553dd612c4bc60178119 Mon Sep 17 00:00:00 2001 -From: Sergey Orlov -Date: Mon, 25 Oct 2021 16:13:15 +0200 -Subject: [PATCH 04/26] ipatests: use AD domain name from config instead of - hardcoded value - -The test fails when test config contains AD domain value other than one -hardcoded in the test code. - -Reviewed-By: Rob Crittenden -(cherry picked from commit f1922fe5017a1e342af7500d875d9a238a48570c) ---- - ipatests/test_integration/test_trust.py | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/ipatests/test_integration/test_trust.py b/ipatests/test_integration/test_trust.py -index 207cddb22..0cb002c74 100644 ---- a/ipatests/test_integration/test_trust.py -+++ b/ipatests/test_integration/test_trust.py -@@ -943,12 +943,12 @@ class TestTrust(BaseTestTrust): - ['chown', '--reference', paths.NAMED_CONF, ad_zone_file]) - named_conf = self.master.get_file_contents(paths.NAMED_CONF, - encoding='utf-8') -- named_conf += textwrap.dedent(''' -- zone "ad.test" {{ -+ named_conf += textwrap.dedent(f''' -+ zone "{self.ad.domain.name}" {{ - type master; -- file "{}"; -+ file "{ad_zone_file}"; - }}; -- '''.format(ad_zone_file)) -+ ''') - self.master.put_file_contents(paths.NAMED_CONF, named_conf) - tasks.restart_named(self.master) - try: --- -2.33.1 - - -From c100c774d928a264314469d160d140fd7d301c21 Mon Sep 17 00:00:00 2001 -From: Florence Blanc-Renaud -Date: Mon, 27 Sep 2021 08:36:32 +0200 -Subject: [PATCH 05/26] SID generation: define SIDInstallInterface - -Move the SID-related options into a separate InstallInterface -(--add-sids, --netbios-name, --rid-base and --secondary-rid-base), -make ADTrustInstallInterface inherit from SIDInstallInterface. - -Related: https://pagure.io/freeipa/issue/8995 -Signed-off-by: Florence Blanc-Renaud -Reviewed-By: Christian Heimes -Reviewed-By: Rob Crittenden -Reviewed-By: Alexander Bokovoy -(cherry picked from commit f9e95ce51e586232497c1d4a9a4a2967a0105f9d) ---- - ipaserver/install/adtrust.py | 56 ++++++++++++++++++++++-------------- - 1 file changed, 35 insertions(+), 21 deletions(-) - -diff --git a/ipaserver/install/adtrust.py b/ipaserver/install/adtrust.py -index ea279b56b..0409743ee 100644 ---- a/ipaserver/install/adtrust.py -+++ b/ipaserver/install/adtrust.py -@@ -530,43 +530,26 @@ def generate_dns_service_records_help(api): - - - @group --class ADTrustInstallInterface(ServiceAdminInstallInterface): -+class SIDInstallInterface(ServiceAdminInstallInterface): - """ -- Interface for the AD trust installer -+ Interface for the SID generation Installer - - Knobs defined here will be available in: - * ipa-server-install - * ipa-replica-install - * ipa-adtrust-install - """ -- description = "AD trust" -- -- # the following knobs are provided on top of those specified for -- # admin credentials -+ description = "SID generation" - add_sids = knob( - None, - description="Add SIDs for existing users and groups as the final step" - ) -- add_agents = knob( -- None, -- description="Add IPA masters to a list of hosts allowed to " -- "serve information about users from trusted forests" -- ) -- add_agents = replica_install_only(add_agents) -- enable_compat = knob( -- None, -- description="Enable support for trusted domains for old clients" -- ) -+ add_sids = replica_install_only(add_sids) - netbios_name = knob( - str, - None, - description="NetBIOS name of the IPA domain" - ) -- no_msdcs = knob( -- None, -- description="Deprecated: has no effect", -- deprecated=True -- ) - rid_base = knob( - int, - 1000, -@@ -578,3 +561,34 @@ class ADTrustInstallInterface(ServiceAdminInstallInterface): - description="Start value of the secondary range for mapping " - "UIDs and GIDs to RIDs" - ) -+ -+ -+@group -+class ADTrustInstallInterface(SIDInstallInterface): -+ """ -+ Interface for the AD trust installer -+ -+ Knobs defined here will be available in: -+ * ipa-server-install -+ * ipa-replica-install -+ * ipa-adtrust-install -+ """ -+ description = "AD trust" -+ -+ # the following knobs are provided on top of those specified for -+ # admin credentials -+ add_agents = knob( -+ None, -+ description="Add IPA masters to a list of hosts allowed to " -+ "serve information about users from trusted forests" -+ ) -+ add_agents = replica_install_only(add_agents) -+ enable_compat = knob( -+ None, -+ description="Enable support for trusted domains for old clients" -+ ) -+ no_msdcs = knob( -+ None, -+ description="Deprecated: has no effect", -+ deprecated=True -+ ) --- -2.33.1 - - -From f1443b92a493c784185761ad7fa4507d51afda59 Mon Sep 17 00:00:00 2001 -From: Florence Blanc-Renaud -Date: Mon, 27 Sep 2021 11:44:43 +0200 -Subject: [PATCH 06/26] Installers: configure sid generation in server/replica - installer - -ADTRUSTInstance performs only sid configuration when it is -called without --setup-adtrust. - -Update man pages for ipa-server-install and ipa-replica-install -with the SID-related options. - -Related: https://pagure.io/freeipa/issue/8995 -Signed-off-by: Florence Blanc-Renaud -Reviewed-By: Christian Heimes -Reviewed-By: Rob Crittenden -Reviewed-By: Alexander Bokovoy -(cherry picked from commit 5541b9d69fdba0df86277756b6ef835b2748d20a) ---- - install/tools/ipa-adtrust-install.in | 2 + - install/tools/man/ipa-replica-install.1 | 30 ++++---- - install/tools/man/ipa-server-install.1 | 11 +-- - ipaserver/install/adtrust.py | 45 +++++------ - ipaserver/install/adtrustinstance.py | 86 +++++++++++++--------- - ipaserver/install/server/__init__.py | 5 -- - ipaserver/install/server/install.py | 11 ++- - ipaserver/install/server/replicainstall.py | 10 ++- - 8 files changed, 113 insertions(+), 87 deletions(-) - -diff --git a/install/tools/ipa-adtrust-install.in b/install/tools/ipa-adtrust-install.in -index 03efc8dec..9cb89ea11 100644 ---- a/install/tools/ipa-adtrust-install.in -+++ b/install/tools/ipa-adtrust-install.in -@@ -209,6 +209,8 @@ def main(): - raise ScriptError( - "Unrecognized error during check of admin rights: %s" % e) - -+ # Force options.setup_adtrust -+ options.setup_adtrust = True - adtrust.install_check(True, options, api) - adtrust.install(True, options, fstore, api) - -diff --git a/install/tools/man/ipa-replica-install.1 b/install/tools/man/ipa-replica-install.1 -index 44fce10ba..7f88303d2 100644 ---- a/install/tools/man/ipa-replica-install.1 -+++ b/install/tools/man/ipa-replica-install.1 -@@ -205,10 +205,7 @@ Do not automatically create DNS SSHFP records. - \fB\-\-no\-dnssec\-validation\fR - Disable DNSSEC validation on this server. - --.SS "AD TRUST OPTIONS" --.TP --\fB\-\-setup\-adtrust\fR --Configure AD Trust capability on a replica. -+.SS "SID GENERATION OPTIONS" - .TP - \fB\-\-netbios\-name\fR=\fINETBIOS_NAME\fR - The NetBIOS name for the IPA domain. If not provided then this is determined -@@ -227,6 +224,21 @@ ipa\-adtrust\-install is run and scheduled independently. To start this task - you have to load an edited version of ipa-sidgen-task-run.ldif with the - ldapmodify command info the directory server. - .TP -+\fB\-\-rid-base\fR=\fIRID_BASE\fR -+First RID value of the local domain. The first Posix ID of the local domain will -+be assigned to this RID, the second to RID+1 etc. See the online help of the -+idrange CLI for details. -+.TP -+\fB\-\-secondary-rid-base\fR=\fISECONDARY_RID_BASE\fR -+Start value of the secondary RID range, which is only used in the case a user -+and a group share numerically the same Posix ID. See the online help of the -+idrange CLI for details. -+ -+.SS "AD TRUST OPTIONS" -+.TP -+\fB\-\-setup\-adtrust\fR -+Configure AD Trust capability on a replica. -+.TP - \fB\-\-add\-agents\fR - Add IPA masters to the list that allows to serve information about - users from trusted forests. Starting with IPA 4.2, a regular IPA master -@@ -240,16 +252,6 @@ information about users from trusted forests only if they are enabled - via \ipa-adtrust\-install run on any other IPA master. At least SSSD - version 1.13 on IPA master is required to be able to perform as a trust agent. - .TP --\fB\-\-rid-base\fR=\fIRID_BASE\fR --First RID value of the local domain. The first Posix ID of the local domain will --be assigned to this RID, the second to RID+1 etc. See the online help of the --idrange CLI for details. --.TP --\fB\-\-secondary-rid-base\fR=\fISECONDARY_RID_BASE\fR --Start value of the secondary RID range, which is only used in the case a user --and a group share numerically the same Posix ID. See the online help of the --idrange CLI for details. --.TP - \fB\-\-enable\-compat\fR - Enables support for trusted domains users for old clients through Schema Compatibility plugin. - SSSD supports trusted domains natively starting with version 1.9. For platforms that -diff --git a/install/tools/man/ipa-server-install.1 b/install/tools/man/ipa-server-install.1 -index 2e89cfc37..fc9251be7 100644 ---- a/install/tools/man/ipa-server-install.1 -+++ b/install/tools/man/ipa-server-install.1 -@@ -230,11 +230,7 @@ Disable DNSSEC validation on this server. - \fB\-\-allow\-zone\-overlap\fR - Allow creation of (reverse) zone even if the zone is already resolvable. Using this option is discouraged as it result in later problems with domain name resolution. - --.SS "AD TRUST OPTIONS" -- --.TP --\fB\-\-setup\-adtrust\fR --Configure AD Trust capability. -+.SS "SID GENERATION OPTIONS" - .TP - \fB\-\-netbios\-name\fR=\fINETBIOS_NAME\fR - The NetBIOS name for the IPA domain. If not provided, this is determined -@@ -252,6 +248,11 @@ idrange CLI for details. - Start value of the secondary RID range, which is only used in the case a user - and a group share numerically the same POSIX ID. See the online help of the - idrange CLI for details. -+ -+.SS "AD TRUST OPTIONS" -+.TP -+\fB\-\-setup\-adtrust\fR -+Configure AD Trust capability. - .TP - \fB\-\-enable\-compat\fR - Enables support for trusted domains users for old clients through Schema Compatibility plugin. -diff --git a/ipaserver/install/adtrust.py b/ipaserver/install/adtrust.py -index 0409743ee..c01748bc0 100644 ---- a/ipaserver/install/adtrust.py -+++ b/ipaserver/install/adtrust.py -@@ -413,7 +413,7 @@ def install_check(standalone, options, api): - global netbios_name - global reset_netbios_name - -- if not standalone: -+ if options.setup_adtrust and not standalone: - check_for_installed_deps() - - realm_not_matching_domain = (api.env.domain.upper() != api.env.realm) -@@ -432,26 +432,27 @@ def install_check(standalone, options, api): - # Check if /etc/samba/smb.conf already exists. In case it was not generated - # by IPA, print a warning that we will break existing configuration. - -- if adtrustinstance.ipa_smb_conf_exists(): -- if not options.unattended: -- print("IPA generated smb.conf detected.") -- if not ipautil.user_input("Overwrite smb.conf?", -- default=False, -- allow_empty=False): -- raise ScriptError("Aborting installation.") -- -- elif os.path.exists(paths.SMB_CONF): -- print("WARNING: The smb.conf already exists. Running " -- "ipa-adtrust-install will break your existing samba " -- "configuration.\n\n") -- if not options.unattended: -- if not ipautil.user_input("Do you wish to continue?", -- default=False, -- allow_empty=False): -- raise ScriptError("Aborting installation.") -- -- if not options.unattended and not options.enable_compat: -- options.enable_compat = enable_compat_tree() -+ if options.setup_adtrust: -+ if adtrustinstance.ipa_smb_conf_exists(): -+ if not options.unattended: -+ print("IPA generated smb.conf detected.") -+ if not ipautil.user_input("Overwrite smb.conf?", -+ default=False, -+ allow_empty=False): -+ raise ScriptError("Aborting installation.") -+ -+ elif os.path.exists(paths.SMB_CONF): -+ print("WARNING: The smb.conf already exists. Running " -+ "ipa-adtrust-install will break your existing samba " -+ "configuration.\n\n") -+ if not options.unattended: -+ if not ipautil.user_input("Do you wish to continue?", -+ default=False, -+ allow_empty=False): -+ raise ScriptError("Aborting installation.") -+ -+ if not options.unattended and not options.enable_compat: -+ options.enable_compat = enable_compat_tree() - - netbios_name, reset_netbios_name = set_and_check_netbios_name( - options.netbios_name, options.unattended, api) -@@ -467,7 +468,7 @@ def install(standalone, options, fstore, api): - print("Please wait until the prompt is returned.") - print("") - -- smb = adtrustinstance.ADTRUSTInstance(fstore) -+ smb = adtrustinstance.ADTRUSTInstance(fstore, options.setup_adtrust) - smb.realm = api.env.realm - smb.autobind = ipaldap.AUTOBIND_ENABLED - smb.setup(api.env.host, api.env.realm, -diff --git a/ipaserver/install/adtrustinstance.py b/ipaserver/install/adtrustinstance.py -index 24e90f3ec..eb9f3cb87 100644 ---- a/ipaserver/install/adtrustinstance.py -+++ b/ipaserver/install/adtrustinstance.py -@@ -149,7 +149,7 @@ class ADTRUSTInstance(service.Service): - OBJC_DOMAIN = "ipaNTDomainAttrs" - FALLBACK_GROUP_NAME = u'Default SMB Group' - -- def __init__(self, fstore=None): -+ def __init__(self, fstore=None, fulltrust=True): - self.netbios_name = None - self.reset_netbios_name = None - self.add_sids = None -@@ -163,10 +163,15 @@ class ADTRUSTInstance(service.Service): - - self.fqdn = None - self.host_netbios_name = None -+ self.fulltrust = fulltrust - -- super(ADTRUSTInstance, self).__init__( -- "smb", service_desc="CIFS", fstore=fstore, service_prefix=u'cifs', -- keytab=paths.SAMBA_KEYTAB) -+ if self.fulltrust: -+ super(ADTRUSTInstance, self).__init__( -+ "smb", service_desc="CIFS", fstore=fstore, -+ service_prefix=u'cifs', -+ keytab=paths.SAMBA_KEYTAB) -+ else: -+ super(ADTRUSTInstance, self).__init__("SID generation") - - self.__setup_default_attributes() - -@@ -200,12 +205,13 @@ class ADTRUSTInstance(service.Service): - api.env.container_cifsdomains, - self.suffix) - -- self.cifs_agent = DN(('krbprincipalname', self.principal.lower()), -- api.env.container_service, -- self.suffix) -- self.host_princ = DN(('fqdn', self.fqdn), -- api.env.container_host, -- self.suffix) -+ if self.fulltrust: -+ self.cifs_agent = DN(('krbprincipalname', self.principal.lower()), -+ api.env.container_service, -+ self.suffix) -+ self.host_princ = DN(('fqdn', self.fqdn), -+ api.env.container_host, -+ self.suffix) - - - def __gen_sid_string(self): -@@ -546,7 +552,7 @@ class ADTRUSTInstance(service.Service): - try: - current = api.Backend.ldap2.get_entry(targets_dn) - members = current.get('memberPrincipal', []) -- if not(self.principal in members): -+ if self.principal not in members: - current["memberPrincipal"] = members + [self.principal] - api.Backend.ldap2.update_entry(current) - else: -@@ -838,45 +844,59 @@ class ADTRUSTInstance(service.Service): - self.sub_dict['IPA_LOCAL_RANGE'] = get_idmap_range(self.realm) - - def create_instance(self): -- self.step("validate server hostname", -- self.__validate_server_hostname) -- self.step("stopping smbd", self.__stop) -+ if self.fulltrust: -+ self.step("validate server hostname", -+ self.__validate_server_hostname) -+ self.step("stopping smbd", self.__stop) - self.step("creating samba domain object", \ - self.__create_samba_domain_object) -- self.step("retrieve local idmap range", self.__retrieve_local_range) -- self.step("writing samba config file", self.__write_smb_conf) -- self.step("creating samba config registry", self.__write_smb_registry) -- self.step("adding cifs Kerberos principal", -- self.request_service_keytab) -- self.step("adding cifs and host Kerberos principals to the adtrust agents group", \ -+ if self.fulltrust: -+ self.step("retrieve local idmap range", -+ self.__retrieve_local_range) -+ self.step("writing samba config file", self.__write_smb_conf) -+ self.step("creating samba config registry", -+ self.__write_smb_registry) -+ self.step("adding cifs Kerberos principal", -+ self.request_service_keytab) -+ self.step("adding cifs and host Kerberos principals to the " -+ "adtrust agents group", - self.__setup_group_membership) -- self.step("check for cifs services defined on other replicas", self.__check_replica) -- self.step("adding cifs principal to S4U2Proxy targets", self.__add_s4u2proxy_target) -+ self.step("check for cifs services defined on other replicas", -+ self.__check_replica) -+ self.step("adding cifs principal to S4U2Proxy targets", -+ self.__add_s4u2proxy_target) - self.step("adding admin(group) SIDs", self.__add_admin_sids) - self.step("adding RID bases", self.__add_rid_bases) - self.step("updating Kerberos config", self.__update_krb5_conf) -- self.step("activating CLDAP plugin", self.__add_cldap_module) -+ if self.fulltrust: -+ self.step("activating CLDAP plugin", self.__add_cldap_module) - self.step("activating sidgen task", self.__add_sidgen_task) -- self.step("map BUILTIN\\Guests to nobody group", -- self.__map_Guests_to_nobody) -- self.step("configuring smbd to start on boot", self.__enable) -+ if self.fulltrust: -+ self.step("map BUILTIN\\Guests to nobody group", -+ self.__map_Guests_to_nobody) -+ self.step("configuring smbd to start on boot", self.__enable) - - if self.enable_compat: -- self.step("enabling trusted domains support for older clients via Schema Compatibility plugin", -+ self.step("enabling trusted domains support for older clients via " -+ "Schema Compatibility plugin", - self.__enable_compat_tree) - -- self.step("restarting Directory Server to take MS PAC and LDAP plugins changes into account", \ -+ self.step("restarting Directory Server to take MS PAC and LDAP " -+ "plugins changes into account", - self.__restart_dirsrv) - self.step("adding fallback group", self.__add_fallback_group) -- self.step("adding Default Trust View", self.__add_default_trust_view) -- self.step("setting SELinux booleans", \ -- self.__configure_selinux_for_smbd) -- self.step("starting CIFS services", self.__start) -+ if self.fulltrust: -+ self.step("adding Default Trust View", -+ self.__add_default_trust_view) -+ self.step("setting SELinux booleans", -+ self.__configure_selinux_for_smbd) -+ self.step("starting CIFS services", self.__start) - - if self.add_sids: - self.step("adding SIDs to existing users and groups", - self.__add_sids) -- self.step("restarting smbd", self.__restart_smb) -+ if self.fulltrust: -+ self.step("restarting smbd", self.__restart_smb) - - self.start_creation(show_service_name=False) - -diff --git a/ipaserver/install/server/__init__.py b/ipaserver/install/server/__init__.py -index f9150ee4e..dd104fa0a 100644 ---- a/ipaserver/install/server/__init__.py -+++ b/ipaserver/install/server/__init__.py -@@ -432,11 +432,6 @@ class ServerInstallInterface(ServerCertificateInstallInterface, - "You cannot specify an --enable-compat option without the " - "--setup-adtrust option") - -- if self.netbios_name: -- raise RuntimeError( -- "You cannot specify a --netbios-name option without the " -- "--setup-adtrust option") -- - if self.no_msdcs: - raise RuntimeError( - "You cannot specify a --no-msdcs option without the " -diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py -index b01fd85a5..5ac68e757 100644 ---- a/ipaserver/install/server/install.py -+++ b/ipaserver/install/server/install.py -@@ -443,6 +443,7 @@ def install_check(installer): - print(" * Configure KRA (dogtag) for secret management") - if options.setup_dns: - print(" * Configure DNS (bind)") -+ print(" * Configure SID generation") - if options.setup_adtrust: - print(" * Configure Samba (smb) and winbind for managing AD trusts") - if not options.no_pkinit: -@@ -703,8 +704,9 @@ def install_check(installer): - logger.debug('Starting Directory Server') - services.knownservices.dirsrv.start(instance_name) - -- if options.setup_adtrust: -- adtrust.install_check(False, options, api) -+ # Always call adtrust.install_check -+ # if --setup-adtrust is not specified, only the SID part is executed -+ adtrust.install_check(False, options, api) - - # installer needs to update hosts file when DNS subsystem will be - # installed or custom addresses are used -@@ -966,8 +968,9 @@ def install(installer): - if options.setup_dns: - dns.install(False, False, options) - -- if options.setup_adtrust: -- adtrust.install(False, options, fstore, api) -+ # Always call adtrust installer to configure SID generation -+ # if --setup-adtrust is not specified, only the SID part is executed -+ adtrust.install(False, options, fstore, api) - - # Set the admin user kerberos password - ds.change_admin_password(admin_password) -diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py -index f1fb91036..1857813c0 100644 ---- a/ipaserver/install/server/replicainstall.py -+++ b/ipaserver/install/server/replicainstall.py -@@ -1158,8 +1158,9 @@ def promote_check(installer): - # check addresses here, dns module is doing own check - no_matching_interface_for_ip_address_warning(config.ips) - -- if options.setup_adtrust: -- adtrust.install_check(False, options, remote_api) -+ # Always call adtrust.install_check -+ # if --setup-adtrust is not specified, only the SID part is executed -+ adtrust.install_check(False, options, remote_api) - - except errors.ACIError: - logger.debug("%s", traceback.format_exc()) -@@ -1365,8 +1366,9 @@ def install(installer): - if options.setup_dns: - dns.install(False, True, options, api) - -- if options.setup_adtrust: -- adtrust.install(False, options, fstore, api) -+ # Always call adtrust.install -+ # if --setup-adtrust is not specified, only the SID part is executed -+ adtrust.install(False, options, fstore, api) - - if options.hidden_replica: - # Set services to hidden --- -2.33.1 - - -From 6d9e346a616055023cfc9d2e237ab56c658734c5 Mon Sep 17 00:00:00 2001 -From: Florence Blanc-Renaud -Date: Fri, 8 Oct 2021 11:37:26 +0200 -Subject: [PATCH 07/26] adtrust install: define constants for rid bases - -Define constants for DEFAULT_PRIMARY_RID_BASE = 1000 and -DEFAULT_SECONDARY_RID_BASE = 100000000 - -Related: https://pagure.io/freeipa/issue/8995 -Signed-off-by: Florence Blanc-Renaud -Reviewed-By: Christian Heimes -Reviewed-By: Rob Crittenden -Reviewed-By: Alexander Bokovoy -(cherry picked from commit b0545326580fa31df6896c29ab2741277b2c775b) ---- - install/tools/ipa-adtrust-install.in | 5 +++-- - ipaserver/install/adtrust.py | 7 +++++-- - 2 files changed, 8 insertions(+), 4 deletions(-) - -diff --git a/install/tools/ipa-adtrust-install.in b/install/tools/ipa-adtrust-install.in -index 9cb89ea11..f245ab342 100644 ---- a/install/tools/ipa-adtrust-install.in -+++ b/install/tools/ipa-adtrust-install.in -@@ -64,10 +64,11 @@ def parse_options(): - parser.add_option("--no-msdcs", dest="no_msdcs", action="store_true", - default=False, help=SUPPRESS_HELP) - -- parser.add_option("--rid-base", dest="rid_base", type=int, default=1000, -+ parser.add_option("--rid-base", dest="rid_base", type=int, -+ default=adtrust.DEFAULT_PRIMARY_RID_BASE, - help="Start value for mapping UIDs and GIDs to RIDs") - parser.add_option("--secondary-rid-base", dest="secondary_rid_base", -- type=int, default=100000000, -+ type=int, default=adtrust.DEFAULT_SECONDARY_RID_BASE, - help="Start value of the secondary range for mapping " - "UIDs and GIDs to RIDs") - parser.add_option("-U", "--unattended", dest="unattended", -diff --git a/ipaserver/install/adtrust.py b/ipaserver/install/adtrust.py -index c01748bc0..6eb6a25ee 100644 ---- a/ipaserver/install/adtrust.py -+++ b/ipaserver/install/adtrust.py -@@ -39,6 +39,9 @@ logger = logging.getLogger(__name__) - netbios_name = None - reset_netbios_name = False - -+DEFAULT_PRIMARY_RID_BASE = 1000 -+DEFAULT_SECONDARY_RID_BASE = 100000000 -+ - - def netbios_name_error(name): - logger.error("\nIllegal NetBIOS name [%s].\n", name) -@@ -553,12 +556,12 @@ class SIDInstallInterface(ServiceAdminInstallInterface): - ) - rid_base = knob( - int, -- 1000, -+ DEFAULT_PRIMARY_RID_BASE, - description="Start value for mapping UIDs and GIDs to RIDs" - ) - secondary_rid_base = knob( - int, -- 100000000, -+ DEFAULT_SECONDARY_RID_BASE, - description="Start value of the secondary range for mapping " - "UIDs and GIDs to RIDs" - ) --- -2.33.1 - - -From 62331da83da61e799d15b86470bccb91f39fff1b Mon Sep 17 00:00:00 2001 -From: Florence Blanc-Renaud -Date: Fri, 8 Oct 2021 15:47:06 +0200 -Subject: [PATCH 08/26] ipa config: add --enable-sid option - -Add new options to ipa config-mod, allowing to enable -SID generation on upgraded servers: -ipa config-mod --enable-sid --add-sids --netbios-name NAME - -The new option uses Dbus to launch an oddjob command, -org.freeipa.server.config-enable-sid -that runs the installation steps related to SID generation. - ---add-sids is optional and triggers the sid generation task that -populates SID for existing users / groups. ---netbios-name is optional and allows to specify the NetBIOS Name. -When not provided, the NetBIOS name is generated based on the leading -component of the DNS domain name. - -This command can be run multiple times. - -Fixes: https://pagure.io/freeipa/issue/8995 -Signed-off-by: Florence Blanc-Renaud -Reviewed-By: Christian Heimes -Reviewed-By: Rob Crittenden -Reviewed-By: Alexander Bokovoy -(cherry picked from commit ed001c97eec092d814ff9ecc57fafffe2d03657e) ---- - API.txt | 5 +- - VERSION.m4 | 4 +- - freeipa.spec.in | 1 + - install/oddjob/Makefile.am | 2 + - .../etc/oddjobd.conf.d/ipa-server.conf.in | 6 ++ - .../org.freeipa.server.config-enable-sid.in | 76 ++++++++++++++ - ipaplatform/base/paths.py | 1 + - ipaserver/install/adtrustinstance.py | 2 + - ipaserver/plugins/config.py | 99 ++++++++++++++++++- - ipaserver/rpcserver.py | 2 + - selinux/ipa.te | 3 + - 11 files changed, 196 insertions(+), 5 deletions(-) - create mode 100644 install/oddjob/org.freeipa.server.config-enable-sid.in - -diff --git a/API.txt b/API.txt -index 6c80028bf..35d95a709 100644 ---- a/API.txt -+++ b/API.txt -@@ -1076,11 +1076,13 @@ args: 0,1,1 - option: Str('version?') - output: Output('result') - command: config_mod/1 --args: 0,29,3 -+args: 0,32,3 -+option: Flag('add_sids?', autofill=True, default=False) - option: Str('addattr*', cli_name='addattr') - option: Flag('all', autofill=True, cli_name='all', default=False) - option: Str('ca_renewal_master_server?', autofill=False) - option: Str('delattr*', cli_name='delattr') -+option: Flag('enable_sid?', autofill=True, default=False) - option: StrEnum('ipaconfigstring*', autofill=False, cli_name='ipaconfigstring', values=[u'AllowNThash', u'KDC:Disable Last Success', u'KDC:Disable Lockout', u'KDC:Disable Default Preauth for SPNs']) - option: Str('ipadefaultemaildomain?', autofill=False, cli_name='emaildomain') - option: Str('ipadefaultloginshell?', autofill=False, cli_name='defaultshell') -@@ -1102,6 +1104,7 @@ option: StrEnum('ipauserauthtype*', autofill=False, cli_name='user_auth_type', v - option: Bool('ipauserdefaultsubordinateid?', autofill=False, cli_name='user_default_subid') - option: Str('ipauserobjectclasses*', autofill=False, cli_name='userobjectclasses') - option: IA5Str('ipausersearchfields?', autofill=False, cli_name='usersearch') -+option: Str('netbios_name?', autofill=False) - option: Flag('raw', autofill=True, cli_name='raw', default=False) - option: Flag('rights', autofill=True, default=False) - option: Str('setattr*', cli_name='setattr') -diff --git a/VERSION.m4 b/VERSION.m4 -index 4a8ef8ba3..87b135d1c 100644 ---- a/VERSION.m4 -+++ b/VERSION.m4 -@@ -86,8 +86,8 @@ define(IPA_DATA_VERSION, 20100614120000) - # # - ######################################################## - define(IPA_API_VERSION_MAJOR, 2) --# Last change: add subordinate id feature --define(IPA_API_VERSION_MINOR, 243) -+# Last change: add enable_sid to config -+define(IPA_API_VERSION_MINOR, 245) - - - ######################################################## -diff --git a/freeipa.spec.in b/freeipa.spec.in -index 9440f3602..36283d93d 100755 ---- a/freeipa.spec.in -+++ b/freeipa.spec.in -@@ -1378,6 +1378,7 @@ fi - %dir %{_libexecdir}/ipa/oddjob - %attr(0755,root,root) %{_libexecdir}/ipa/oddjob/org.freeipa.server.conncheck - %attr(0755,root,root) %{_libexecdir}/ipa/oddjob/org.freeipa.server.trust-enable-agent -+%attr(0755,root,root) %{_libexecdir}/ipa/oddjob/org.freeipa.server.config-enable-sid - %config(noreplace) %{_sysconfdir}/dbus-1/system.d/org.freeipa.server.conf - %config(noreplace) %{_sysconfdir}/oddjobd.conf.d/ipa-server.conf - %dir %{_libexecdir}/ipa/certmonger -diff --git a/install/oddjob/Makefile.am b/install/oddjob/Makefile.am -index 7aeb406a2..bd968eaba 100644 ---- a/install/oddjob/Makefile.am -+++ b/install/oddjob/Makefile.am -@@ -7,6 +7,7 @@ dbusconfdir = $(sysconfdir)/dbus-1/system.d - dist_noinst_DATA = \ - com.redhat.idm.trust-fetch-domains.in \ - org.freeipa.server.trust-enable-agent.in \ -+ org.freeipa.server.config-enable-sid.in \ - etc/oddjobd.conf.d/oddjobd-ipa-trust.conf.in \ - etc/oddjobd.conf.d/ipa-server.conf.in \ - $(NULL) -@@ -18,6 +19,7 @@ dist_oddjob_SCRIPTS = \ - nodist_oddjob_SCRIPTS = \ - com.redhat.idm.trust-fetch-domains \ - org.freeipa.server.trust-enable-agent \ -+ org.freeipa.server.config-enable-sid \ - $(NULL) - - -diff --git a/install/oddjob/etc/oddjobd.conf.d/ipa-server.conf.in b/install/oddjob/etc/oddjobd.conf.d/ipa-server.conf.in -index 640b510aa..a79640f88 100644 ---- a/install/oddjob/etc/oddjobd.conf.d/ipa-server.conf.in -+++ b/install/oddjob/etc/oddjobd.conf.d/ipa-server.conf.in -@@ -17,6 +17,12 @@ - prepend_user_name="no" - argument_passing_method="cmdline"/> - -+ -+ -+ - - - -diff --git a/install/oddjob/org.freeipa.server.config-enable-sid.in b/install/oddjob/org.freeipa.server.config-enable-sid.in -new file mode 100644 -index 000000000..ff5fb49e2 ---- /dev/null -+++ b/install/oddjob/org.freeipa.server.config-enable-sid.in -@@ -0,0 +1,76 @@ -+#!/usr/bin/python3 -+# -+# Copyright (C) 2021 FreeIPA Contributors see COPYING for license -+# -+ -+import logging -+ -+from ipalib import api -+from ipalib.install import sysrestore -+from ipaplatform.paths import paths -+from ipapython import ipaldap -+from ipapython.admintool import AdminTool -+from ipaserver.install import adtrust, adtrustinstance -+ -+logger = logging.getLogger(__name__) -+ -+class IPAConfigEnableSid(AdminTool): -+ command_name = "ipa-enable-sid" -+ log_file_name = paths.IPASERVER_ENABLESID_LOG -+ usage = "%prog" -+ description = "Enable SID generation" -+ -+ @classmethod -+ def add_options(cls, parser): -+ super(IPAConfigEnableSid, cls).add_options(parser) -+ -+ parser.add_option( -+ "--add-sids", -+ dest="add_sids", default=False, action="store_true", -+ help="Add SIDs for existing users and groups as the final step" -+ ) -+ -+ parser.add_option( -+ "--netbios-name", -+ dest="netbios_name", default=None, -+ help="NetBIOS name of the IPA domain" -+ ) -+ -+ parser.add_option( -+ "--reset-netbios-name", -+ dest="reset_netbios_name", default=False, action="store_true", -+ help="Force reset of the existing NetBIOS name" -+ ) -+ -+ -+ def validate_options(self): -+ super(IPAConfigEnableSid, self).validate_options(needs_root=True) -+ -+ def run(self): -+ api.bootstrap(in_server=True, confdir=paths.ETC_IPA) -+ api.finalize() -+ -+ try: -+ api.Backend.ldap2.connect() -+ fstore = sysrestore.FileStore(paths.SYSRESTORE) -+ -+ smb = adtrustinstance.ADTRUSTInstance(fstore, False) -+ smb.realm = api.env.realm -+ smb.autobind = ipaldap.AUTOBIND_ENABLED -+ smb.setup(api.env.host, api.env.realm, -+ self.options.netbios_name, -+ self.options.reset_netbios_name, -+ adtrust.DEFAULT_PRIMARY_RID_BASE, -+ adtrust.DEFAULT_SECONDARY_RID_BASE, -+ self.options.add_sids, -+ enable_compat=False) -+ smb.find_local_id_range() -+ smb.create_instance() -+ -+ finally: -+ if api.Backend.ldap2.isconnected(): -+ api.Backend.ldap2.disconnect() -+ -+ return 0 -+ -+IPAConfigEnableSid.run_cli() -diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py -index de217d9ef..42a47f1df 100644 ---- a/ipaplatform/base/paths.py -+++ b/ipaplatform/base/paths.py -@@ -364,6 +364,7 @@ class BasePathNamespace: - IPAREPLICA_CONNCHECK_LOG = "/var/log/ipareplica-conncheck.log" - IPAREPLICA_INSTALL_LOG = "/var/log/ipareplica-install.log" - IPARESTORE_LOG = "/var/log/iparestore.log" -+ IPASERVER_ENABLESID_LOG = "/var/log/ipaserver-enable-sid.log" - IPASERVER_INSTALL_LOG = "/var/log/ipaserver-install.log" - IPASERVER_ADTRUST_INSTALL_LOG = "/var/log/ipaserver-adtrust-install.log" - IPASERVER_DNS_INSTALL_LOG = "/var/log/ipaserver-dns-install.log" -diff --git a/ipaserver/install/adtrustinstance.py b/ipaserver/install/adtrustinstance.py -index eb9f3cb87..8d4d9263f 100644 ---- a/ipaserver/install/adtrustinstance.py -+++ b/ipaserver/install/adtrustinstance.py -@@ -335,6 +335,8 @@ class ADTRUSTInstance(service.Service): - # _ldap_mod does not return useful error codes, so we must check again - # if the fallback group was created properly. - try: -+ # Remove entry from cache otherwise get_entry won't find it -+ api.Backend.ldap2.remove_cache_entry(fb_group_dn) - api.Backend.ldap2.get_entry(fb_group_dn) - except errors.NotFound: - self.print_msg("Failed to add fallback group.") -diff --git a/ipaserver/plugins/config.py b/ipaserver/plugins/config.py -index ad3dd6a7f..eae401fc3 100644 ---- a/ipaserver/plugins/config.py -+++ b/ipaserver/plugins/config.py -@@ -17,12 +17,16 @@ - # - # You should have received a copy of the GNU General Public License - # along with this program. If not, see . -+import dbus -+import dbus.mainloop.glib -+import logging - - from ipalib import api --from ipalib import Bool, Int, Str, IA5Str, StrEnum, DNParam -+from ipalib import Bool, Int, Str, IA5Str, StrEnum, DNParam, Flag - from ipalib import errors - from ipalib.constants import MAXHOSTNAMELEN - from ipalib.plugable import Registry -+from ipalib.request import context - from ipalib.util import validate_domain_name - from .baseldap import ( - LDAPObject, -@@ -30,7 +34,12 @@ from .baseldap import ( - LDAPRetrieve) - from .selinuxusermap import validate_selinuxuser - from ipalib import _ -+from ipapython.admintool import ScriptError - from ipapython.dn import DN -+from ipaserver.plugins.privilege import principal_has_privilege -+from ipaserver.install.adtrust import set_and_check_netbios_name -+ -+logger = logging.getLogger(__name__) - - # 389-ds attributes that should be skipped in attribute checks - OPERATIONAL_ATTRIBUTES = ('nsaccountlock', 'member', 'memberof', -@@ -340,6 +349,24 @@ class config(LDAPObject): - doc=_('DNSec key master'), - flags={'virtual_attribute', 'no_create', 'no_update'} - ), -+ Flag( -+ 'enable_sid?', -+ label=_('Setup SID configuration'), -+ doc=_('New users and groups automatically get a SID assigned'), -+ flags={'virtual_attribute', 'no_create'} -+ ), -+ Flag( -+ 'add_sids?', -+ label=_('Add SIDs'), -+ doc=_('Add SIDs for existing users and groups'), -+ flags={'virtual_attribute', 'no_create'} -+ ), -+ Str( -+ 'netbios_name?', -+ label=_('NetBIOS name of the IPA domain'), -+ doc=_('NetBIOS name of the IPA domain'), -+ flags={'virtual_attribute', 'no_create'} -+ ), - ) - - def get_dn(self, *keys, **kwargs): -@@ -479,6 +506,60 @@ class config(LDAPObject): - class config_mod(LDAPUpdate): - __doc__ = _('Modify configuration options.') - -+ def _enable_sid(self, ldap, options): -+ # the user must have the Replication Administrators privilege -+ privilege = 'Replication Administrators' -+ if not principal_has_privilege(self.api, context.principal, privilege): -+ raise errors.ACIError( -+ info=_("not allowed to enable SID generation")) -+ -+ # NetBIOS name is either taken from options or generated -+ try: -+ netbios_name, reset_netbios_name = set_and_check_netbios_name( -+ options.get('netbios_name', None), True, self.api) -+ except ScriptError: -+ raise errors.ValidationError(name="NetBIOS name", -+ error=_('Up to 15 characters and only uppercase ASCII letters' -+ ', digits and dashes are allowed. Empty string is ' -+ 'not allowed.')) -+ -+ _ret = 0 -+ _stdout = '' -+ _stderr = '' -+ -+ dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) -+ -+ method_options = [] -+ if options.get('add_sids', False): -+ method_options.extend(["--add-sids"]) -+ method_options.extend(["--netbios-name", netbios_name]) -+ if reset_netbios_name: -+ method_options.append("--reset-netbios-name") -+ # Dbus definition expects up to 10 arguments -+ method_options.extend([''] * (10 - len(method_options))) -+ -+ try: -+ bus = dbus.SystemBus() -+ obj = bus.get_object('org.freeipa.server', '/', -+ follow_name_owner_changes=True) -+ server = dbus.Interface(obj, 'org.freeipa.server') -+ _ret, _stdout, _stderr = server.config_enable_sid(*method_options) -+ except dbus.DBusException as e: -+ logger.error('Failed to call org.freeipa.server.config_enable_sid.' -+ 'DBus exception is %s', str(e)) -+ raise errors.ExecutionError(message=_('Failed to call DBus')) -+ -+ # The oddjob restarts dirsrv, we need to re-establish the conn -+ if self.api.Backend.ldap2.isconnected(): -+ self.api.Backend.ldap2.disconnect() -+ self.api.Backend.ldap2.connect(ccache=context.ccache_name) -+ -+ if _ret != 0: -+ logger.error("Helper config_enable_sid return code is %d", _ret) -+ raise errors.ExecutionError( -+ message=_('Configuration of SID failed. ' -+ 'See details in the error log')) -+ - def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): - assert isinstance(dn, DN) - if 'ipadefaultprimarygroup' in entry_attrs: -@@ -606,13 +687,27 @@ class config_mod(LDAPUpdate): - - self.obj.validate_domain_resolution_order(entry_attrs) - -+ # The options add_sids or netbios_name need the enable_sid option -+ for sid_option in ['add_sids', 'netbios_name']: -+ if options.get(sid_option, None) and not options['enable_sid']: -+ opt = "--" + sid_option.replace("_", "-") -+ error_message = _("You cannot specify %s without " -+ "the --enable-sid option" % opt) -+ raise errors.ValidationError( -+ name=opt, -+ error=error_message) -+ -+ if options['enable_sid']: -+ self._enable_sid(ldap, options) -+ - return dn - - def exc_callback(self, keys, options, exc, call_func, - *call_args, **call_kwargs): - if (isinstance(exc, errors.EmptyModlist) and - call_func.__name__ == 'update_entry' and -- 'ca_renewal_master_server' in options): -+ ('ca_renewal_master_server' in options or -+ 'enable_sid' in options)): - return - - super(config_mod, self).exc_callback( -diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py -index e612528e0..20c536e4d 100644 ---- a/ipaserver/rpcserver.py -+++ b/ipaserver/rpcserver.py -@@ -383,6 +383,8 @@ class WSGIExecutioner(Executioner): - if self.api.env.debug: - time_start = time.perf_counter_ns() - try: -+ if 'KRB5CCNAME' in environ: -+ setattr(context, "ccache_name", environ['KRB5CCNAME']) - if ('HTTP_ACCEPT_LANGUAGE' in environ): - lang_reg_w_q = environ['HTTP_ACCEPT_LANGUAGE'].split(',')[0] - lang_reg = lang_reg_w_q.split(';')[0] -diff --git a/selinux/ipa.te b/selinux/ipa.te -index 68e109419..cfca2e7c3 100644 ---- a/selinux/ipa.te -+++ b/selinux/ipa.te -@@ -155,6 +155,9 @@ manage_dirs_pattern(ipa_helper_t, ipa_var_run_t, ipa_var_run_t) - manage_files_pattern(ipa_helper_t, ipa_var_run_t, ipa_var_run_t) - files_pid_filetrans(ipa_helper_t, ipa_var_run_t, { dir file }) - -+manage_files_pattern(ipa_helper_t, ipa_tmp_t, ipa_tmp_t) -+files_tmp_filetrans(ipa_helper_t, ipa_tmp_t, { file }) -+ - kernel_read_system_state(ipa_helper_t) - kernel_read_network_state(ipa_helper_t) - --- -2.33.1 - - -From b3bcd710060a0da45afddaf78cb35f0b12f8ef05 Mon Sep 17 00:00:00 2001 -From: Florence Blanc-Renaud -Date: Fri, 8 Oct 2021 17:43:15 +0200 -Subject: [PATCH 09/26] ipatests: add test ensuring SIDs are generated for new - installs - -The standard installer now configures all the items needed -for SID generation. Add a new test with the following scenario: -- install IPA server -- create an active user -- ensure the user's entry has an attribute ipantsecurityidentifier -- ensure that the kerberos ticket for the user contains PAC data -by using the utility ipa-print-pac - -Related: https://pagure.io/freeipa/issue/8995 -Signed-off-by: Florence Blanc-Renaud -Reviewed-By: Christian Heimes -Reviewed-By: Rob Crittenden -Reviewed-By: Alexander Bokovoy -(cherry picked from commit 8dc064c2e3011b78f76659e60f47185edca0d64e) ---- - ipatests/test_integration/test_commands.py | 40 ++++++++++++++++++++++ - 1 file changed, 40 insertions(+) - -diff --git a/ipatests/test_integration/test_commands.py b/ipatests/test_integration/test_commands.py -index 4d9a81652..51a26b4b0 100644 ---- a/ipatests/test_integration/test_commands.py -+++ b/ipatests/test_integration/test_commands.py -@@ -1578,6 +1578,46 @@ class TestIPACommandWithoutReplica(IntegrationTest): - tasks.ldapsearch_dm(self.master, base, ldap_args=[], scope='sub') - tasks.ldapsearch_dm(self.master, base, ldap_args=[], scope='base') - -+ def test_sid_generation(self): -+ """ -+ Test SID generation -+ -+ Check that new users are created with a SID and PAC data is -+ added in their Kerberos tickets. -+ """ -+ user = "pacuser" -+ passwd = "Secret123" -+ -+ try: -+ # Create a nonadmin user -+ tasks.create_active_user( -+ self.master, user, passwd, first=user, last=user, -+ krb5_trace=True) -+ -+ # Check SID is present in the new entry -+ base_dn = str(self.master.domain.basedn) -+ result = tasks.ldapsearch_dm( -+ self.master, -+ 'uid={user},cn=users,cn=accounts,{base_dn}'.format( -+ user=user, base_dn=base_dn), -+ ['ipantsecurityidentifier'], -+ scope='base' -+ ) -+ assert 'ipantsecurityidentifier' in result.stdout_text -+ -+ # Defaults: host/... principal for service -+ # keytab in /etc/krb5.keytab -+ self.master.run_command(["kinit", '-k']) -+ result = self.master.run_command( -+ [os.path.join(paths.LIBEXEC_IPA_DIR, "ipa-print-pac"), -+ "ticket", user], -+ stdin_text=(passwd + '\n') -+ ) -+ assert "PAC_DATA" in result.stdout_text -+ finally: -+ tasks.kinit_admin(self.master) -+ self.master.run_command(['ipa', 'user-del', user]) -+ - - class TestIPAautomount(IntegrationTest): - @classmethod --- -2.33.1 - - -From 14eb748fb73c98f2492f11863ce99f8f71ff7cca Mon Sep 17 00:00:00 2001 -From: Florence Blanc-Renaud -Date: Tue, 12 Oct 2021 09:57:27 +0200 -Subject: [PATCH 10/26] ipatests: interactive install prompts for netbios name - -The interactive server installation now prompts for netbios -name confirmation. -Add expected prompt and send response to the installer. - -Related: https://pagure.io/freeipa/issue/8995 -Signed-off-by: Florence Blanc-Renaud -Reviewed-By: Christian Heimes -Reviewed-By: Rob Crittenden -Reviewed-By: Alexander Bokovoy -(cherry picked from commit 2d468fa49f1d5b99cc27004c417cbc47602cf719) ---- - ipalib/constants.py | 3 +++ - ipaserver/install/adtrustinstance.py | 6 ++---- - ipatests/test_integration/test_caless.py | 1 + - .../test_integration/test_installation.py | 19 +++++++++++++++++++ - ipatests/test_integration/test_ntp_options.py | 3 +++ - 5 files changed, 28 insertions(+), 4 deletions(-) - -diff --git a/ipalib/constants.py b/ipalib/constants.py -index 2aeafac7a..fb5fd95ff 100644 ---- a/ipalib/constants.py -+++ b/ipalib/constants.py -@@ -23,6 +23,7 @@ All constants centralised in one file. - """ - - import os -+import string - - from ipaplatform.constants import constants as _constants - from ipapython.dn import DN -@@ -368,3 +369,5 @@ KRA_TRACKING_REQS = { - 'transportCert cert-pki-kra': 'caTransportCert', - 'storageCert cert-pki-kra': 'caStorageCert', - } -+ -+ALLOWED_NETBIOS_CHARS = string.ascii_uppercase + string.digits + '-' -diff --git a/ipaserver/install/adtrustinstance.py b/ipaserver/install/adtrustinstance.py -index 8d4d9263f..af5c14a7e 100644 ---- a/ipaserver/install/adtrustinstance.py -+++ b/ipaserver/install/adtrustinstance.py -@@ -25,7 +25,6 @@ import errno - import ldap - import tempfile - import uuid --import string - import struct - import re - import socket -@@ -36,7 +35,8 @@ from ipaserver.install import service - from ipaserver.install import installutils - from ipaserver.install.replication import wait_for_task - from ipalib import errors, api --from ipalib.constants import SUBID_RANGE_START -+from ipalib.constants import SUBID_RANGE_START, ALLOWED_NETBIOS_CHARS -+ - from ipalib.util import normalize_zone - from ipapython.dn import DN - from ipapython import ipachangeconf -@@ -54,8 +54,6 @@ if six.PY3: - - logger = logging.getLogger(__name__) - --ALLOWED_NETBIOS_CHARS = string.ascii_uppercase + string.digits + '-' -- - UPGRADE_ERROR = """ - Entry %(dn)s does not exist. - This means upgrade from IPA 2.x to 3.x did not went well and required S4U2Proxy -diff --git a/ipatests/test_integration/test_caless.py b/ipatests/test_integration/test_caless.py -index 16dfbb320..4481845da 100644 ---- a/ipatests/test_integration/test_caless.py -+++ b/ipatests/test_integration/test_caless.py -@@ -60,6 +60,7 @@ def get_install_stdin(cert_passwords=()): - '', # Server host name (has default) - ] - lines.extend(cert_passwords) # Enter foo.p12 unlock password -+ lines.extend('IPA') # NetBios name - lines += [ - 'no', # configure chrony with NTP server or pool address? - 'yes', # Continue with these values? -diff --git a/ipatests/test_integration/test_installation.py b/ipatests/test_integration/test_installation.py -index e3c41eaa1..3a44f5ed8 100644 ---- a/ipatests/test_integration/test_installation.py -+++ b/ipatests/test_integration/test_installation.py -@@ -22,6 +22,7 @@ from cryptography import x509 as crypto_x509 - from ipalib import x509 - from ipalib.constants import DOMAIN_LEVEL_0, KRA_TRACKING_REQS - from ipalib.constants import IPA_CA_RECORD -+from ipalib.constants import ALLOWED_NETBIOS_CHARS - from ipalib.sysrestore import SYSRESTORE_STATEFILE, SYSRESTORE_INDEXFILE - from ipapython.dn import DN - from ipaplatform.constants import constants -@@ -69,6 +70,17 @@ def server_cleanup(request): - tasks.uninstall_master(host) - - -+def create_netbios_name(host): -+ """ -+ Create a NetBIOS name based on the provided host -+ """ -+ netbios = ''.join( -+ c for c in host.domain.name.split('.')[0].upper() \ -+ if c in ALLOWED_NETBIOS_CHARS -+ )[:15] -+ return netbios -+ -+ - class InstallTestBase1(IntegrationTest): - - num_replicas = 3 -@@ -1171,6 +1183,8 @@ class TestInstallMaster(IntegrationTest): - hosts = self.master.get_file_contents(paths.HOSTS, encoding='utf-8') - new_hosts = hosts.replace(original_hostname, new_hostname) - self.master.put_file_contents(paths.HOSTS, new_hosts) -+ netbios = create_netbios_name(self.master) -+ - try: - cmd = ['ipa-server-install', '--hostname', new_hostname] - with self.master.spawn_expect(cmd) as e: -@@ -1193,6 +1207,8 @@ class TestInstallMaster(IntegrationTest): - e.sendline(self.master.config.admin_password) - e.expect_exact('Password (confirm): ') - e.sendline(self.master.config.admin_password) -+ e.expect_exact('NetBIOS domain name [{}]: '.format(netbios)) -+ e.sendline(netbios) - e.expect_exact('Do you want to configure chrony with ' - 'NTP server or pool address? [no]: ') - e.sendline('no') -@@ -1367,6 +1383,7 @@ class TestInstallMasterDNS(IntegrationTest): - https://pagure.io/freeipa/issue/2575 - """ - cmd = ['ipa-server-install'] -+ netbios = create_netbios_name(self.master) - with self.master.spawn_expect(cmd) as e: - e.expect_exact('Do you want to configure integrated ' - 'DNS (BIND)? [no]: ') -@@ -1398,6 +1415,8 @@ class TestInstallMasterDNS(IntegrationTest): - e.expect_exact('Do you want to search for missing reverse ' - 'zones? [yes]: ') - e.sendline('no') # irrelevant for this test -+ e.expect_exact('NetBIOS domain name [{}]: '.format(netbios)) -+ e.sendline(netbios) - e.expect_exact('Do you want to configure chrony with NTP ' - 'server or pool address? [no]: ') - e.sendline('no') # irrelevant for this test -diff --git a/ipatests/test_integration/test_ntp_options.py b/ipatests/test_integration/test_ntp_options.py -index 27d35043e..efd950991 100644 ---- a/ipatests/test_integration/test_ntp_options.py -+++ b/ipatests/test_integration/test_ntp_options.py -@@ -260,6 +260,8 @@ class TestNTPoptions(IntegrationTest): - "No\n" - # Server host name [hostname]: - "\n" -+ # Enter the NetBIOS name for the IPA domain -+ "IPA\n" - # Do you want to configure chrony with NTP server - # or pool address? [no]: - "Yes\n" -@@ -372,6 +374,7 @@ class TestNTPoptions(IntegrationTest): - server_input = ( - "\n" + - "\n" -+ "IPA\n" - "No\n" - "Yes" - ) --- -2.33.1 - - -From 1eb811fe872246866a3e093026213beceefa0493 Mon Sep 17 00:00:00 2001 -From: Florence Blanc-Renaud -Date: Fri, 15 Oct 2021 12:46:36 +0200 -Subject: [PATCH 11/26] ipatests: adapt expected output with SID - -From now on, new users/groups automatically get a SID. -Update the expect test outputs. - -Related: https://pagure.io/freeipa/issue/8995 -Signed-off-by: Florence Blanc-Renaud -Reviewed-By: Christian Heimes -Reviewed-By: Rob Crittenden -Reviewed-By: Alexander Bokovoy -(cherry picked from commit fdfde9ce52e87309acdd1ad394dc79c0ee3b901f) ---- - ipatests/test_xmlrpc/mock_trust.py | 45 ------------------- - ipatests/test_xmlrpc/objectclasses.py | 4 +- - ipatests/test_xmlrpc/test_batch_plugin.py | 7 ++- - ipatests/test_xmlrpc/test_group_plugin.py | 25 ++++++----- - ipatests/test_xmlrpc/test_idviews_plugin.py | 19 ++++---- - .../test_kerberos_principal_aliases.py | 6 +-- - ipatests/test_xmlrpc/test_netgroup_plugin.py | 4 +- - ipatests/test_xmlrpc/test_range_plugin.py | 2 + - .../test_xmlrpc/test_selinuxusermap_plugin.py | 4 +- - ipatests/test_xmlrpc/test_service_plugin.py | 7 ++- - ipatests/test_xmlrpc/test_trust_plugin.py | 4 +- - ipatests/test_xmlrpc/test_user_plugin.py | 27 ++++++----- - ipatests/test_xmlrpc/tracker/group_plugin.py | 11 +++-- - ipatests/test_xmlrpc/tracker/user_plugin.py | 9 ++-- - ipatests/test_xmlrpc/xmlrpc_test.py | 12 ++--- - 15 files changed, 85 insertions(+), 101 deletions(-) - -diff --git a/ipatests/test_xmlrpc/mock_trust.py b/ipatests/test_xmlrpc/mock_trust.py -index 08c1c2914..24a26ed1d 100644 ---- a/ipatests/test_xmlrpc/mock_trust.py -+++ b/ipatests/test_xmlrpc/mock_trust.py -@@ -2,55 +2,10 @@ - # - # Copyright (C) 2016 FreeIPA Contributors see COPYING for license - # --from contextlib import contextmanager - import six - - from ipalib import api --from ipatests.util import MockLDAP - --trust_container_dn = "cn=ad,cn=trusts,{basedn}".format( -- basedn=api.env.basedn) --trust_container_add = dict( -- objectClass=[b"nsContainer", b"top"] -- ) -- --smb_cont_dn = "{cifsdomains},{basedn}".format( -- cifsdomains=api.env.container_cifsdomains, -- basedn=api.env.basedn) --smb_cont_add = dict( -- objectClass=[b"nsContainer", b"top"] -- ) -- -- --def create_mock_trust_containers(): -- with MockLDAP() as ldap: -- ldap.add_entry(trust_container_dn, trust_container_add) -- ldap.add_entry(smb_cont_dn, smb_cont_add) -- -- --def remove_mock_trust_containers(): -- with MockLDAP() as ldap: -- ldap.del_entry(trust_container_dn) -- ldap.del_entry(smb_cont_dn) -- -- --@contextmanager --def mocked_trust_containers(): -- """Mocked trust containers -- -- Provides containers for the RPC tests: -- cn=ad,cn=trusts,BASEDN -- cn=ad,cn=etc,BASEDN -- -- Upon exiting, it tries to remove the container entries. -- If the user of the context manager failed to remove -- all child entries, exiting the context manager will fail. -- """ -- create_mock_trust_containers() -- try: -- yield -- finally: -- remove_mock_trust_containers() - - def get_range_dn(name): - format_str = "cn={name},cn=ranges,cn=etc,{basedn}" -diff --git a/ipatests/test_xmlrpc/objectclasses.py b/ipatests/test_xmlrpc/objectclasses.py -index 6a0efdd18..23bc03a07 100644 ---- a/ipatests/test_xmlrpc/objectclasses.py -+++ b/ipatests/test_xmlrpc/objectclasses.py -@@ -35,7 +35,7 @@ user_base = [ - u'ipaSshGroupOfPubKeys', - ] - --user = user_base + [u'mepOriginEntry'] -+user = user_base + [u'mepOriginEntry', 'ipantuserattrs',] - - group = [ - u'top', -@@ -46,7 +46,7 @@ group = [ - ] - - externalgroup = group + [u'ipaexternalgroup'] --posixgroup = group + [u'posixgroup'] -+posixgroup = group + [u'posixgroup', 'ipantgroupattrs'] - - host = [ - u'ipasshhost', -diff --git a/ipatests/test_xmlrpc/test_batch_plugin.py b/ipatests/test_xmlrpc/test_batch_plugin.py -index e475081e3..632dd2c79 100644 ---- a/ipatests/test_xmlrpc/test_batch_plugin.py -+++ b/ipatests/test_xmlrpc/test_batch_plugin.py -@@ -25,6 +25,7 @@ from ipalib import api - from ipatests.test_xmlrpc import objectclasses - from ipatests.util import Fuzzy, assert_deepequal - from ipatests.test_xmlrpc.xmlrpc_test import (Declarative, fuzzy_digits, -+ fuzzy_set_optional_oc, - fuzzy_uuid) - from ipapython.dn import DN - import pytest -@@ -97,7 +98,8 @@ class test_batch(Declarative): - result=dict( - cn=[group1], - description=[u'Test desc 1'], -- objectclass=objectclasses.group + [u'posixgroup'], -+ objectclass=fuzzy_set_optional_oc( -+ objectclasses.posixgroup, 'ipantgroupattrs'), - ipauniqueid=[fuzzy_uuid], - gidnumber=[fuzzy_digits], - dn=DN(('cn', 'testgroup1'), -@@ -168,7 +170,8 @@ class test_batch(Declarative): - result=dict( - cn=[group1], - description=[u'Test desc 1'], -- objectclass=objectclasses.group + [u'posixgroup'], -+ objectclass=fuzzy_set_optional_oc( -+ objectclasses.posixgroup, 'ipantgroupattrs'), - ipauniqueid=[fuzzy_uuid], - gidnumber=[fuzzy_digits], - dn=DN(('cn', 'testgroup1'), -diff --git a/ipatests/test_xmlrpc/test_group_plugin.py b/ipatests/test_xmlrpc/test_group_plugin.py -index 11c85feb4..f9a0e2cfe 100644 ---- a/ipatests/test_xmlrpc/test_group_plugin.py -+++ b/ipatests/test_xmlrpc/test_group_plugin.py -@@ -27,7 +27,8 @@ import pytest - from ipalib import errors - from ipatests.test_xmlrpc import objectclasses - from ipatests.test_xmlrpc.xmlrpc_test import ( -- fuzzy_digits, fuzzy_uuid, fuzzy_set_ci, add_oc, -+ fuzzy_digits, fuzzy_uuid, fuzzy_set_ci, -+ fuzzy_user_or_group_sid, - XMLRPC_test, raises_exact - ) - from ipatests.test_xmlrpc.tracker.group_plugin import GroupTracker -@@ -61,6 +62,8 @@ def managed_group(request, user): - tracker.exists = True - # Managed group gets created when user is created - tracker.track_create() -+ # Managed groups don't have a SID -+ del tracker.attrs['ipantsecurityidentifier'] - return tracker - - -@@ -79,7 +82,7 @@ def user_npg2(request, group): - del tracker.attrs['mepmanagedentry'] - tracker.attrs.update( - gidnumber=[u'1000'], description=[], memberof_group=[group.cn], -- objectclass=add_oc(objectclasses.user_base, u'ipantuserattrs') -+ objectclass=objectclasses.user_base + ['ipantuserattrs'] - ) - return tracker.make_fixture(request) - -@@ -314,9 +317,9 @@ class TestFindGroup(XMLRPC_test): - 'gidnumber': [fuzzy_digits], - 'cn': [u'admins'], - 'description': [u'Account administrators group'], -- 'objectclass': fuzzy_set_ci(add_oc( -- objectclasses.posixgroup, u'ipantgroupattrs')), -+ 'objectclass': fuzzy_set_ci(objectclasses.posixgroup), - 'ipauniqueid': [fuzzy_uuid], -+ 'ipantsecurityidentifier': [fuzzy_user_or_group_sid], - }, - { - 'dn': get_group_dn('editors'), -@@ -324,27 +327,27 @@ class TestFindGroup(XMLRPC_test): - 'cn': [u'editors'], - 'description': - [u'Limited admins who can edit other users'], -- 'objectclass': fuzzy_set_ci(add_oc( -- objectclasses.posixgroup, u'ipantgroupattrs')), -+ 'objectclass': fuzzy_set_ci(objectclasses.posixgroup), - 'ipauniqueid': [fuzzy_uuid], -+ 'ipantsecurityidentifier': [fuzzy_user_or_group_sid], - }, - { - 'dn': get_group_dn(group.cn), - 'cn': [group.cn], - 'description': [u'Test desc1'], - 'gidnumber': [fuzzy_digits], -- 'objectclass': fuzzy_set_ci(add_oc( -- objectclasses.posixgroup, u'ipantgroupattrs')), -+ 'objectclass': fuzzy_set_ci(objectclasses.posixgroup), - 'ipauniqueid': [fuzzy_uuid], -+ 'ipantsecurityidentifier': [fuzzy_user_or_group_sid], - }, - { - 'dn': get_group_dn(group2.cn), - 'cn': [group2.cn], - 'description': [u'Test desc2'], - 'gidnumber': [fuzzy_digits], -- 'objectclass': fuzzy_set_ci(add_oc( -- objectclasses.posixgroup, u'ipantgroupattrs')), -+ 'objectclass': fuzzy_set_ci(objectclasses.posixgroup), - 'ipauniqueid': [fuzzy_uuid], -+ 'ipantsecurityidentifier': [fuzzy_user_or_group_sid], - }, - ]), result) - -@@ -498,6 +501,8 @@ class TestExternalGroup(XMLRPC_test): - group.track_create() - del group.attrs['gidnumber'] - group.attrs.update(objectclass=objectclasses.externalgroup) -+ # External group don't have a SID -+ del group.attrs['ipantsecurityidentifier'] - command = group.make_create_command(**dict(external=True)) - result = command() - group.check_create(result) -diff --git a/ipatests/test_xmlrpc/test_idviews_plugin.py b/ipatests/test_xmlrpc/test_idviews_plugin.py -index be96e27dc..fa535af7a 100644 ---- a/ipatests/test_xmlrpc/test_idviews_plugin.py -+++ b/ipatests/test_xmlrpc/test_idviews_plugin.py -@@ -27,7 +27,8 @@ import six - - from ipalib import api, errors - from ipatests.test_xmlrpc import objectclasses --from ipatests.test_xmlrpc.xmlrpc_test import (Declarative, uuid_re, add_oc, -+from ipatests.test_xmlrpc.xmlrpc_test import (Declarative, uuid_re, -+ fuzzy_set_optional_oc, - fuzzy_uuid, fuzzy_digits) - from ipatests.test_xmlrpc.test_user_plugin import get_user_result - from ipatests.test_xmlrpc.test_group_plugin import get_group_dn -@@ -216,10 +217,7 @@ class test_idviews(Declarative): - u'Test', - u'User1', - 'add', -- objectclass=add_oc( -- objectclasses.user, -- u'ipantuserattrs' -- ) -+ objectclass=objectclasses.user, - ), - ), - ), -@@ -237,7 +235,8 @@ class test_idviews(Declarative): - result=dict( - cn=[idoverridegroup1], - description=[u'Test desc 1'], -- objectclass=objectclasses.posixgroup, -+ objectclass=fuzzy_set_optional_oc( -+ objectclasses.posixgroup, 'ipantgroupattrs'), - ipauniqueid=[fuzzy_uuid], - gidnumber=[fuzzy_digits], - dn=get_group_dn(idoverridegroup1), -@@ -1624,10 +1623,7 @@ class test_idviews(Declarative): - u'Removed', - u'User', - 'add', -- objectclass=add_oc( -- objectclasses.user, -- u'ipantuserattrs' -- ) -+ objectclass=objectclasses.user, - ), - ), - ), -@@ -1645,7 +1641,8 @@ class test_idviews(Declarative): - result=dict( - cn=[idoverridegroup_removed], - description=[u'Removed group'], -- objectclass=objectclasses.posixgroup, -+ objectclass=fuzzy_set_optional_oc( -+ objectclasses.posixgroup, 'ipantgroupattrs'), - ipauniqueid=[fuzzy_uuid], - gidnumber=[fuzzy_digits], - dn=get_group_dn(idoverridegroup_removed), -diff --git a/ipatests/test_xmlrpc/test_kerberos_principal_aliases.py b/ipatests/test_xmlrpc/test_kerberos_principal_aliases.py -index 61d3684bd..91c22b08c 100644 ---- a/ipatests/test_xmlrpc/test_kerberos_principal_aliases.py -+++ b/ipatests/test_xmlrpc/test_kerberos_principal_aliases.py -@@ -19,7 +19,7 @@ from ipatests.test_xmlrpc.tracker.host_plugin import HostTracker - from ipatests.test_xmlrpc.tracker.service_plugin import ServiceTracker - from ipatests.test_xmlrpc.tracker.stageuser_plugin import StageUserTracker - from ipatests.test_xmlrpc.mock_trust import ( -- mocked_trust_containers, get_trust_dn, get_trusted_dom_dict, -+ get_trust_dn, get_trusted_dom_dict, - encode_mockldap_value) - from ipatests.util import unlock_principal_password, change_principal - -@@ -62,7 +62,7 @@ def trusted_domain(): - trusted_dom = TRUSTED_DOMAIN_MOCK - - # Write the changes -- with mocked_trust_containers(), MockLDAP() as ldap: -+ with MockLDAP() as ldap: - ldap.add_entry(trusted_dom['dn'], trusted_dom['ldif']) - yield trusted_dom - ldap.del_entry(trusted_dom['dn']) -@@ -83,7 +83,7 @@ def trusted_domain_with_suffix(): - ) - - # Write the changes -- with mocked_trust_containers(), MockLDAP() as ldap: -+ with MockLDAP() as ldap: - ldap.add_entry(trusted_dom['dn'], trusted_dom['ldif']) - yield trusted_dom - ldap.del_entry(trusted_dom['dn']) -diff --git a/ipatests/test_xmlrpc/test_netgroup_plugin.py b/ipatests/test_xmlrpc/test_netgroup_plugin.py -index 5004ecbe8..3f1fc0bc1 100644 ---- a/ipatests/test_xmlrpc/test_netgroup_plugin.py -+++ b/ipatests/test_xmlrpc/test_netgroup_plugin.py -@@ -24,6 +24,7 @@ Test the `ipaserver/plugins/netgroup.py` module. - from ipalib import api - from ipalib import errors - from ipatests.test_xmlrpc.xmlrpc_test import (Declarative, fuzzy_digits, -+ fuzzy_set_optional_oc, - fuzzy_uuid, fuzzy_netgroupdn) - from ipatests.test_xmlrpc import objectclasses - from ipapython.dn import DN -@@ -300,7 +301,8 @@ class test_netgroup(Declarative): - cn=[group1], - description=[u'Test desc 1'], - gidnumber=[fuzzy_digits], -- objectclass=objectclasses.group + [u'posixgroup'], -+ objectclass=fuzzy_set_optional_oc( -+ objectclasses.posixgroup, 'ipantgroupattrs'), - ipauniqueid=[fuzzy_uuid], - dn=DN(('cn',group1),('cn','groups'),('cn','accounts'), - api.env.basedn), -diff --git a/ipatests/test_xmlrpc/test_range_plugin.py b/ipatests/test_xmlrpc/test_range_plugin.py -index ef683f84e..387e0ed9f 100644 ---- a/ipatests/test_xmlrpc/test_range_plugin.py -+++ b/ipatests/test_xmlrpc/test_range_plugin.py -@@ -502,6 +502,8 @@ class test_range(Declarative): - user1, u'Test', u'User1', 'add', - uidnumber=[unicode(user1_uid)], - gidnumber=[unicode(user1_uid)], -+ objectclass=objectclasses.user_base + [u'mepOriginEntry'], -+ omit=['ipantsecurityidentifier'], - ), - ), - ), -diff --git a/ipatests/test_xmlrpc/test_selinuxusermap_plugin.py b/ipatests/test_xmlrpc/test_selinuxusermap_plugin.py -index 179b65b6a..662212a63 100644 ---- a/ipatests/test_xmlrpc/test_selinuxusermap_plugin.py -+++ b/ipatests/test_xmlrpc/test_selinuxusermap_plugin.py -@@ -25,6 +25,7 @@ from ipaplatform.constants import constants as platformconstants - - from ipatests.test_xmlrpc import objectclasses - from ipatests.test_xmlrpc.xmlrpc_test import (Declarative, fuzzy_digits, -+ fuzzy_set_optional_oc, - fuzzy_uuid) - from ipapython.dn import DN - from ipatests.util import Fuzzy -@@ -230,7 +231,8 @@ class test_selinuxusermap(Declarative): - cn=[group1], - description=[u'Test desc 1'], - gidnumber=[fuzzy_digits], -- objectclass=objectclasses.group + [u'posixgroup'], -+ objectclass=fuzzy_set_optional_oc( -+ objectclasses.posixgroup, 'ipantgroupattrs'), - ipauniqueid=[fuzzy_uuid], - dn=DN(('cn', group1), ('cn', 'groups'), ('cn', 'accounts'), - api.env.basedn), -diff --git a/ipatests/test_xmlrpc/test_service_plugin.py b/ipatests/test_xmlrpc/test_service_plugin.py -index ed634a045..a3e5b740b 100644 ---- a/ipatests/test_xmlrpc/test_service_plugin.py -+++ b/ipatests/test_xmlrpc/test_service_plugin.py -@@ -25,6 +25,7 @@ from ipalib import api, errors - from ipatests.test_xmlrpc.xmlrpc_test import Declarative, fuzzy_uuid, fuzzy_hash - from ipatests.test_xmlrpc.xmlrpc_test import fuzzy_digits, fuzzy_date, fuzzy_issuer - from ipatests.test_xmlrpc.xmlrpc_test import fuzzy_hex, XMLRPC_test -+from ipatests.test_xmlrpc.xmlrpc_test import fuzzy_set_optional_oc - from ipatests.test_xmlrpc.xmlrpc_test import raises_exact - from ipatests.test_xmlrpc import objectclasses - from ipatests.test_xmlrpc.testcert import get_testcert, subject_base -@@ -1113,7 +1114,8 @@ class test_service_allowed_to(Declarative): - summary=u'Added group "%s"' % group1, - result=dict( - cn=[group1], -- objectclass=objectclasses.group + [u'posixgroup'], -+ objectclass=fuzzy_set_optional_oc( -+ objectclasses.posixgroup, 'ipantgroupattrs'), - ipauniqueid=[fuzzy_uuid], - gidnumber=[fuzzy_digits], - dn=group1_dn -@@ -1165,7 +1167,8 @@ class test_service_allowed_to(Declarative): - summary=u'Added group "%s"' % group2, - result=dict( - cn=[group2], -- objectclass=objectclasses.group + [u'posixgroup'], -+ objectclass=fuzzy_set_optional_oc( -+ objectclasses.posixgroup, 'ipantgroupattrs'), - ipauniqueid=[fuzzy_uuid], - gidnumber=[fuzzy_digits], - dn=group2_dn -diff --git a/ipatests/test_xmlrpc/test_trust_plugin.py b/ipatests/test_xmlrpc/test_trust_plugin.py -index 21c170943..9c91db438 100644 ---- a/ipatests/test_xmlrpc/test_trust_plugin.py -+++ b/ipatests/test_xmlrpc/test_trust_plugin.py -@@ -27,6 +27,7 @@ from ipapython.dn import DN - from ipatests.test_xmlrpc import objectclasses - from ipatests.test_xmlrpc.xmlrpc_test import ( - Declarative, fuzzy_guid, fuzzy_domain_sid, fuzzy_string, fuzzy_uuid, -+ fuzzy_set_optional_oc, - fuzzy_digits) - import pytest - -@@ -110,7 +111,8 @@ class test_trustconfig(Declarative): - cn=[testgroup], - description=[u'Test group'], - gidnumber=[fuzzy_digits], -- objectclass=objectclasses.group + [u'posixgroup'], -+ objectclass=fuzzy_set_optional_oc( -+ objectclasses.posixgroup, 'ipantgroupattrs'), - ipauniqueid=[fuzzy_uuid], - dn=testgroup_dn, - ), -diff --git a/ipatests/test_xmlrpc/test_user_plugin.py b/ipatests/test_xmlrpc/test_user_plugin.py -index 19af031bc..c2b8f79c8 100644 ---- a/ipatests/test_xmlrpc/test_user_plugin.py -+++ b/ipatests/test_xmlrpc/test_user_plugin.py -@@ -38,7 +38,8 @@ from ipatests.util import ( - assert_deepequal, assert_equal, assert_not_equal, raises) - from ipatests.test_xmlrpc.xmlrpc_test import ( - XMLRPC_test, fuzzy_digits, fuzzy_uuid, fuzzy_password, -- Fuzzy, fuzzy_dergeneralizedtime, add_sid, add_oc, raises_exact) -+ fuzzy_user_or_group_sid, -+ Fuzzy, fuzzy_dergeneralizedtime, raises_exact) - from ipapython.dn import DN - from ipapython.ipaldap import ldap_initialize - -@@ -124,7 +125,7 @@ def user_npg(request, group): - del tracker.attrs['mepmanagedentry'] - tracker.attrs.update( - description=[], memberof_group=[group.cn], -- objectclass=add_oc(objectclasses.user_base, u'ipantuserattrs') -+ objectclass=objectclasses.user_base + [u'ipantuserattrs'], - ) - return tracker.make_fixture(request) - -@@ -138,7 +139,7 @@ def user_npg2(request, group): - del tracker.attrs['mepmanagedentry'] - tracker.attrs.update( - gidnumber=[u'1000'], description=[], memberof_group=[group.cn], -- objectclass=add_oc(objectclasses.user_base, u'ipantuserattrs') -+ objectclass=objectclasses.user_base + [u'ipantuserattrs'], - ) - return tracker.make_fixture(request) - -@@ -645,7 +646,7 @@ class TestCreate(XMLRPC_test): - testuser.attrs.update(gidnumber=[u'1000']) - testuser.attrs.update( - description=[], -- objectclass=add_oc(objectclasses.user_base, u'ipantuserattrs') -+ objectclass=objectclasses.user_base + [u'ipantuserattrs'] - ) - command = testuser.make_create_command() - result = command() -@@ -659,9 +660,12 @@ class TestCreate(XMLRPC_test): - name=u'tuser1', givenname=u'Test', sn=u'Tuser1', uidnumber=999 - ) - testuser.track_create() -+ # When uid is outside of IPA id range, no SID is generated -+ del testuser.attrs['ipantsecurityidentifier'] - testuser.attrs.update( - uidnumber=[u'999'], -- gidnumber=[u'999'] -+ gidnumber=[u'999'], -+ objectclass=objectclasses.user_base + ['mepOriginEntry'] - ) - command = testuser.make_create_command() - result = command() -@@ -837,7 +841,7 @@ class TestUserWithUPGDisabled(XMLRPC_test): - testuser.attrs.update(gidnumber=[u'1000']) - testuser.attrs.update( - description=[], -- objectclass=add_oc(objectclasses.user_base, u'ipantuserattrs') -+ objectclass=objectclasses.user_base + [u'ipantuserattrs'], - ) - command = testuser.make_create_command() - result = command() -@@ -860,7 +864,7 @@ class TestUserWithUPGDisabled(XMLRPC_test): - testuser.attrs.update(gidnumber=[u'1000']) - testuser.attrs.update( - description=[], -- objectclass=add_oc(objectclasses.user_base, u'ipantuserattrs') -+ objectclass=objectclasses.user_base + [u'ipantuserattrs'], - ) - command = testuser.make_create_command() - result = command() -@@ -1147,7 +1151,7 @@ def get_user_result(uid, givenname, sn, operation='show', omit=[], - # sn can be None; this should only be used from `get_admin_result` - cn = overrides.get('cn', ['%s %s' % (givenname, sn or '')]) - cn[0] = cn[0].strip() -- result = add_sid(dict( -+ result = dict( - homedirectory=[u'/home/%s' % uid], - loginshell=[platformconstants.DEFAULT_SHELL], - uid=[uid], -@@ -1158,7 +1162,7 @@ def get_user_result(uid, givenname, sn, operation='show', omit=[], - mail=[u'%s@%s' % (uid, api.env.domain)], - has_keytab=False, - has_password=False, -- )) -+ ) - if sn: - result['sn'] = [sn] - if givenname: -@@ -1175,9 +1179,10 @@ def get_user_result(uid, givenname, sn, operation='show', omit=[], - initials=[givenname[0] + (sn or '')[:1]], - ipauniqueid=[fuzzy_uuid], - mepmanagedentry=[get_group_dn(uid)], -- objectclass=add_oc(objectclasses.user, u'ipantuserattrs'), -+ objectclass=objectclasses.user, - krbprincipalname=[u'%s@%s' % (uid, api.env.realm)], -- krbcanonicalname=[u'%s@%s' % (uid, api.env.realm)] -+ krbcanonicalname=[u'%s@%s' % (uid, api.env.realm)], -+ ipantsecurityidentifier=[fuzzy_user_or_group_sid], - ) - if operation in ('show', 'show-all', 'find', 'mod'): - result.update( -diff --git a/ipatests/test_xmlrpc/tracker/group_plugin.py b/ipatests/test_xmlrpc/tracker/group_plugin.py -index 8a6f8516e..fb36d7cf1 100644 ---- a/ipatests/test_xmlrpc/tracker/group_plugin.py -+++ b/ipatests/test_xmlrpc/tracker/group_plugin.py -@@ -4,6 +4,8 @@ - - from ipatests.test_xmlrpc import objectclasses - from ipatests.test_xmlrpc.xmlrpc_test import fuzzy_digits, fuzzy_uuid -+from ipatests.test_xmlrpc.xmlrpc_test import fuzzy_user_or_group_sid -+from ipatests.test_xmlrpc.xmlrpc_test import fuzzy_set_optional_oc - - from ipatests.test_xmlrpc.tracker.base import Tracker - from ipatests.util import assert_deepequal, get_group_dn -@@ -21,9 +23,10 @@ class GroupTracker(Tracker): - 'idoverrideuser' - } - -- retrieve_all_keys = retrieve_keys | {u'ipauniqueid', u'objectclass'} -+ retrieve_all_keys = retrieve_keys | {u'ipauniqueid', u'objectclass', -+ 'ipantsecurityidentifier'} - -- create_keys = retrieve_all_keys -+ create_keys = retrieve_all_keys - {u'ipantsecurityidentifier'} - update_keys = retrieve_keys - {u'dn'} - - add_member_keys = retrieve_keys | {u'description'} -@@ -91,7 +94,9 @@ class GroupTracker(Tracker): - description=[self.description], - gidnumber=[fuzzy_digits], - ipauniqueid=[fuzzy_uuid], -- objectclass=objectclasses.posixgroup, -+ objectclass=fuzzy_set_optional_oc( -+ objectclasses.posixgroup, 'ipantgroupattrs'), -+ ipantsecurityidentifier=[fuzzy_user_or_group_sid], - ) - self.exists = True - -diff --git a/ipatests/test_xmlrpc/tracker/user_plugin.py b/ipatests/test_xmlrpc/tracker/user_plugin.py -index d5e9ca893..9adbe8d92 100644 ---- a/ipatests/test_xmlrpc/tracker/user_plugin.py -+++ b/ipatests/test_xmlrpc/tracker/user_plugin.py -@@ -11,7 +11,7 @@ import six - from ipatests.util import assert_deepequal, get_group_dn - from ipatests.test_xmlrpc import objectclasses - from ipatests.test_xmlrpc.xmlrpc_test import ( -- fuzzy_digits, fuzzy_uuid, raises_exact) -+ fuzzy_digits, fuzzy_uuid, fuzzy_user_or_group_sid, raises_exact) - from ipatests.test_xmlrpc.tracker.base import Tracker - from ipatests.test_xmlrpc.tracker.kerberos_aliases import KerberosAliasMixin - from ipatests.test_xmlrpc.tracker.certmapdata import CertmapdataMixin -@@ -40,7 +40,8 @@ class UserTracker(CertmapdataMixin, KerberosAliasMixin, Tracker): - u'l', u'mobile', u'krbextradata', u'krblastpwdchange', - u'krbpasswordexpiration', u'pager', u'st', u'manager', u'cn', - u'ipauniqueid', u'objectclass', u'mepmanagedentry', -- u'displayname', u'gecos', u'initials', u'preserved'} -+ u'displayname', u'gecos', u'initials', u'preserved', -+ 'ipantsecurityidentifier'} - - retrieve_preserved_keys = (retrieve_keys - {u'memberof_group'}) | { - u'preserved'} -@@ -122,7 +123,8 @@ class UserTracker(CertmapdataMixin, KerberosAliasMixin, Tracker): - api.env.container_deleteuser, - api.env.basedn - ) -- self.attrs[u'objectclass'] = objectclasses.user_base -+ self.attrs[u'objectclass'] = objectclasses.user_base \ -+ + ['ipantuserattrs'] - - return self.make_command( - 'user_del', self.uid, -@@ -188,6 +190,7 @@ class UserTracker(CertmapdataMixin, KerberosAliasMixin, Tracker): - mepmanagedentry=[get_group_dn(self.uid)], - memberof_group=[u'ipausers'], - nsaccountlock=[u'false'], -+ ipantsecurityidentifier=[fuzzy_user_or_group_sid], - ) - - for key in self.kwargs: -diff --git a/ipatests/test_xmlrpc/xmlrpc_test.py b/ipatests/test_xmlrpc/xmlrpc_test.py -index de2357237..8adb3c0d7 100644 ---- a/ipatests/test_xmlrpc/xmlrpc_test.py -+++ b/ipatests/test_xmlrpc/xmlrpc_test.py -@@ -137,6 +137,12 @@ fuzzy_bytes = Fuzzy(type=bytes) - def fuzzy_set_ci(s): - return Fuzzy(test=lambda other: set(x.lower() for x in other) == set(y.lower() for y in s)) - -+ -+def fuzzy_set_optional_oc(s, oc): -+ return Fuzzy(test=lambda other: set(x.lower() for x in other if x != oc) -+ == set(y.lower() for y in s if y != oc)) -+ -+ - try: - if not api.Backend.rpcclient.isconnected(): - api.Backend.rpcclient.connect() -@@ -152,12 +158,6 @@ adtrust_is_enabled = api.Command['adtrust_is_enabled']()['result'] - sidgen_was_run = api.Command['sidgen_was_run']()['result'] - - --def add_sid(d, check_sidgen=False): -- if adtrust_is_enabled and (not check_sidgen or sidgen_was_run): -- d['ipantsecurityidentifier'] = (fuzzy_user_or_group_sid,) -- return d -- -- - def add_oc(l, oc, check_sidgen=False): - if adtrust_is_enabled and (not check_sidgen or sidgen_was_run): - return l + [oc] --- -2.33.1 - - -From ad330cbee12744c1a6fe43881b915b281ba9e9c2 Mon Sep 17 00:00:00 2001 -From: Florence Blanc-Renaud -Date: Fri, 15 Oct 2021 15:55:10 +0200 -Subject: [PATCH 12/26] User lifecycle: ignore SID when moving from preserved - to staged - -When a preserved user entry is moved to staged state, the SID -attribute must not be provided to user-stage command (the option -does not exist and the SID will be re-generated anyway). - -Related: https://pagure.io/freeipa/issue/8995 -Signed-off-by: Florence Blanc-Renaud -Reviewed-By: Christian Heimes -Reviewed-By: Rob Crittenden -Reviewed-By: Alexander Bokovoy -(cherry picked from commit fd53ed14b0e43c6d3020ed54907011cbacb6716f) ---- - ipaserver/plugins/user.py | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/ipaserver/plugins/user.py b/ipaserver/plugins/user.py -index 19d07e6d6..b9ac09008 100644 ---- a/ipaserver/plugins/user.py -+++ b/ipaserver/plugins/user.py -@@ -1002,6 +1002,7 @@ class user_stage(LDAPMultiQuery): - u'ipauniqueid', u'krbcanonicalname', - u'sshpubkeyfp', u'krbextradata', - u'ipacertmapdata', -+ 'ipantsecurityidentifier', - u'nsaccountlock'] - - def execute(self, *keys, **options): --- -2.33.1 - - -From 939f7ceea66ba11aa66bd31104f5b2f364dff998 Mon Sep 17 00:00:00 2001 -From: Florence Blanc-Renaud -Date: Wed, 20 Oct 2021 10:43:33 +0200 -Subject: [PATCH 13/26] ipatests: backup-reinstall-restore needs to clear sssd - cache - -The integration tests that check backup-reinstall-restore -scenario need to clear sssd cache before checking the uid -of the admin user. For instance: -backup: saves the original admin uid -reinstall: creates a new admin uid, potentially cached by SSSD -restore: restores the original admin uid - -Related: https://pagure.io/freeipa/issue/8995 -Signed-off-by: Florence Blanc-Renaud -Reviewed-By: Christian Heimes -Reviewed-By: Rob Crittenden -Reviewed-By: Alexander Bokovoy -(cherry picked from commit c99b8bb4abbbfc9611185adc1b1168cce2c79cf3) ---- - .../test_integration/test_backup_and_restore.py | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - -diff --git a/ipatests/test_integration/test_backup_and_restore.py b/ipatests/test_integration/test_backup_and_restore.py -index dcaddb1a1..a10c96f80 100644 ---- a/ipatests/test_integration/test_backup_and_restore.py -+++ b/ipatests/test_integration/test_backup_and_restore.py -@@ -311,6 +311,11 @@ class BaseBackupAndRestoreWithDNS(IntegrationTest): - tasks.install_master(self.master, setup_dns=True) - self.master.run_command(['ipa-restore', backup_path], - stdin_text=dirman_password + '\nyes') -+ if reinstall: -+ # If the server was reinstalled, reinstall may have changed -+ # the uid and restore reverts to the original value. -+ # clear the cache to make sure we get up-to-date values -+ tasks.clear_sssd_cache(self.master) - tasks.resolve_record(self.master.ip, self.example_test_zone) - - tasks.kinit_admin(self.master) -@@ -380,6 +385,12 @@ class BaseBackupAndRestoreWithDNSSEC(IntegrationTest): - self.master.run_command(['ipa-restore', backup_path], - stdin_text=dirman_password + '\nyes') - -+ if reinstall: -+ # If the server was reinstalled, reinstall may have changed -+ # the uid and restore reverts to the original value. -+ # clear the cache to make sure we get up-to-date values -+ tasks.clear_sssd_cache(self.master) -+ - assert ( - wait_until_record_is_signed( - self.master.ip, self.example_test_zone) -@@ -464,6 +475,12 @@ class BaseBackupAndRestoreWithKRA(IntegrationTest): - self.master.run_command(['ipa-restore', backup_path], - stdin_text=dirman_password + '\nyes') - -+ if reinstall: -+ # If the server was reinstalled, reinstall may have changed -+ # the uid and restore reverts to the original value. -+ # clear the cache to make sure we get up-to-date values -+ tasks.clear_sssd_cache(self.master) -+ - tasks.kinit_admin(self.master) - # retrieve secret after restore - self.master.run_command([ --- -2.33.1 - - -From 0f7c3a6b249e88f193d5745ba2af3e2d435b91cb Mon Sep 17 00:00:00 2001 -From: Florence Blanc-Renaud -Date: Thu, 21 Oct 2021 15:15:45 +0200 -Subject: [PATCH 14/26] Webui tests: new idrange now requires base RID - -Now that SID are always generated, the creation of a new -local idrange is refused if baserid is missing. - -Related: https://pagure.io/freeipa/issue/8995 -Signed-off-by: Florence Blanc-Renaud -Reviewed-By: Christian Heimes -Reviewed-By: Rob Crittenden -Reviewed-By: Alexander Bokovoy -(cherry picked from commit 02b4241e19967e4b27fc0bf73ad38a1f4ac87497) ---- - ipatests/test_webui/test_range.py | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - -diff --git a/ipatests/test_webui/test_range.py b/ipatests/test_webui/test_range.py -index 239c1c442..a72def452 100644 ---- a/ipatests/test_webui/test_range.py -+++ b/ipatests/test_webui/test_range.py -@@ -297,8 +297,13 @@ class test_range(range_tasks): - - # Without primary and secondary RID bases - data = self.get_data(pkey, base_rid='', secondary_base_rid='') -- self.add_record(ENTITY, data, navigate=False) -- self.delete_record(pkey) -+ self.add_record(ENTITY, data, navigate=False, negative=True) -+ try: -+ assert self.has_form_error('ipabaserid') -+ finally: -+ self.delete_record(pkey) -+ -+ self.dialog_button_click('cancel') - - @screenshot - def test_modify_range_with_invalid_or_missing_values(self): --- -2.33.1 - - -From e53972dbb8bf22bb66fb49c09464d9d481a590d2 Mon Sep 17 00:00:00 2001 -From: Florence Blanc-Renaud -Date: Thu, 21 Oct 2021 15:18:12 +0200 -Subject: [PATCH 15/26] User plugin: do not return the SID on user creation - -The SID is not part of the default user attributes and does not -need to be returned in the user-add output. - -Related: https://pagure.io/freeipa/issue/8995 -Reviewed-By: Christian Heimes -Reviewed-By: Rob Crittenden -Reviewed-By: Alexander Bokovoy -(cherry picked from commit bede62bf199544dc91cc33e74adccb2b0166ef60) ---- - ipaserver/plugins/user.py | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/ipaserver/plugins/user.py b/ipaserver/plugins/user.py -index b9ac09008..ffca80782 100644 ---- a/ipaserver/plugins/user.py -+++ b/ipaserver/plugins/user.py -@@ -659,6 +659,10 @@ class user_add(baseuser_add): - - entry_attrs.update(newentry) - -+ # delete ipantsecurityidentifier if present -+ if ('ipantsecurityidentifier' in entry_attrs): -+ del entry_attrs['ipantsecurityidentifier'] -+ - if options.get('random', False): - try: - entry_attrs['randompassword'] = unicode(getattr(context, 'randompassword')) --- -2.33.1 - - -From 968e1a3e0b2158560262f5733a3ba83e232d8b68 Mon Sep 17 00:00:00 2001 -From: Florence Blanc-Renaud -Date: Thu, 21 Oct 2021 15:22:25 +0200 -Subject: [PATCH 16/26] ipatests: update the expected output of user-add cmd - -The SID is not expected to be returned by ipa user-add. - -Related: https://pagure.io/freeipa/issue/8995 -Signed-off-by: Florence Blanc-Renaud -Reviewed-By: Christian Heimes -Reviewed-By: Rob Crittenden -Reviewed-By: Alexander Bokovoy -(cherry picked from commit cc8a0bc24c50abfb609bc3767b4a550e1f72e1f6) ---- - ipatests/test_xmlrpc/test_idviews_plugin.py | 6 ++++-- - ipatests/test_xmlrpc/test_range_plugin.py | 1 - - ipatests/test_xmlrpc/test_user_plugin.py | 3 +++ - ipatests/test_xmlrpc/tracker/user_plugin.py | 5 ++++- - 4 files changed, 11 insertions(+), 4 deletions(-) - -diff --git a/ipatests/test_xmlrpc/test_idviews_plugin.py b/ipatests/test_xmlrpc/test_idviews_plugin.py -index fa535af7a..9b31f5d13 100644 ---- a/ipatests/test_xmlrpc/test_idviews_plugin.py -+++ b/ipatests/test_xmlrpc/test_idviews_plugin.py -@@ -217,7 +217,8 @@ class test_idviews(Declarative): - u'Test', - u'User1', - 'add', -- objectclass=objectclasses.user, -+ objectclass=fuzzy_set_optional_oc( -+ objectclasses.user, 'ipantuserattrs'), - ), - ), - ), -@@ -1623,7 +1624,8 @@ class test_idviews(Declarative): - u'Removed', - u'User', - 'add', -- objectclass=objectclasses.user, -+ objectclass=fuzzy_set_optional_oc( -+ objectclasses.user, 'ipantuserattrs'), - ), - ), - ), -diff --git a/ipatests/test_xmlrpc/test_range_plugin.py b/ipatests/test_xmlrpc/test_range_plugin.py -index 387e0ed9f..f912e0474 100644 ---- a/ipatests/test_xmlrpc/test_range_plugin.py -+++ b/ipatests/test_xmlrpc/test_range_plugin.py -@@ -503,7 +503,6 @@ class test_range(Declarative): - uidnumber=[unicode(user1_uid)], - gidnumber=[unicode(user1_uid)], - objectclass=objectclasses.user_base + [u'mepOriginEntry'], -- omit=['ipantsecurityidentifier'], - ), - ), - ), -diff --git a/ipatests/test_xmlrpc/test_user_plugin.py b/ipatests/test_xmlrpc/test_user_plugin.py -index c2b8f79c8..b093a9f2b 100644 ---- a/ipatests/test_xmlrpc/test_user_plugin.py -+++ b/ipatests/test_xmlrpc/test_user_plugin.py -@@ -1182,6 +1182,9 @@ def get_user_result(uid, givenname, sn, operation='show', omit=[], - objectclass=objectclasses.user, - krbprincipalname=[u'%s@%s' % (uid, api.env.realm)], - krbcanonicalname=[u'%s@%s' % (uid, api.env.realm)], -+ ) -+ if operation == 'show-all': -+ result.update( - ipantsecurityidentifier=[fuzzy_user_or_group_sid], - ) - if operation in ('show', 'show-all', 'find', 'mod'): -diff --git a/ipatests/test_xmlrpc/tracker/user_plugin.py b/ipatests/test_xmlrpc/tracker/user_plugin.py -index 9adbe8d92..6cfb9518f 100644 ---- a/ipatests/test_xmlrpc/tracker/user_plugin.py -+++ b/ipatests/test_xmlrpc/tracker/user_plugin.py -@@ -11,6 +11,7 @@ import six - from ipatests.util import assert_deepequal, get_group_dn - from ipatests.test_xmlrpc import objectclasses - from ipatests.test_xmlrpc.xmlrpc_test import ( -+ fuzzy_set_optional_oc, - fuzzy_digits, fuzzy_uuid, fuzzy_user_or_group_sid, raises_exact) - from ipatests.test_xmlrpc.tracker.base import Tracker - from ipatests.test_xmlrpc.tracker.kerberos_aliases import KerberosAliasMixin -@@ -51,6 +52,7 @@ class UserTracker(CertmapdataMixin, KerberosAliasMixin, Tracker): - u'krbextradata', u'krbpasswordexpiration', u'krblastpwdchange', - u'krbprincipalkey', u'userpassword', u'randompassword'} - create_keys = create_keys - {u'nsaccountlock'} -+ create_keys = create_keys - {'ipantsecurityidentifier'} - - update_keys = retrieve_keys - {u'dn'} - activate_keys = retrieve_keys -@@ -175,7 +177,8 @@ class UserTracker(CertmapdataMixin, KerberosAliasMixin, Tracker): - displayname=[u'%s %s' % (self.givenname, self.sn)], - cn=[u'%s %s' % (self.givenname, self.sn)], - initials=[u'%s%s' % (self.givenname[0], self.sn[0])], -- objectclass=objectclasses.user, -+ objectclass=fuzzy_set_optional_oc( -+ objectclasses.user, 'ipantuserattrs'), - description=[u'__no_upg__'], - ipauniqueid=[fuzzy_uuid], - uidnumber=[fuzzy_digits], --- -2.33.1 - - -From 459965ec7915b94ce98e8c4c54e34e7b2e6756f0 Mon Sep 17 00:00:00 2001 -From: Florence Blanc-Renaud -Date: Wed, 10 Nov 2021 10:54:37 +0100 -Subject: [PATCH 17/26] ipatests: fix get_user_result method - -Because the sidgen plugin is a postop plugin, it is not -always triggered before the result of an ADD is returned -and the objectclasses of the user may / may not contain -ipantuserattrs. -Fix the get_user_result method to work in all the cases. - -Related: https://pagure.io/freeipa/issue/8995 -Signed-off-by: Florence Blanc-Renaud -Reviewed-By: Alexander Bokovoy -(cherry picked from commit 2e7396b0e2869e1c5025903cf752e7d90e163a0a) ---- - ipatests/test_xmlrpc/test_user_plugin.py | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/ipatests/test_xmlrpc/test_user_plugin.py b/ipatests/test_xmlrpc/test_user_plugin.py -index b093a9f2b..58996b213 100644 ---- a/ipatests/test_xmlrpc/test_user_plugin.py -+++ b/ipatests/test_xmlrpc/test_user_plugin.py -@@ -38,7 +38,7 @@ from ipatests.util import ( - assert_deepequal, assert_equal, assert_not_equal, raises) - from ipatests.test_xmlrpc.xmlrpc_test import ( - XMLRPC_test, fuzzy_digits, fuzzy_uuid, fuzzy_password, -- fuzzy_user_or_group_sid, -+ fuzzy_user_or_group_sid, fuzzy_set_optional_oc, - Fuzzy, fuzzy_dergeneralizedtime, raises_exact) - from ipapython.dn import DN - from ipapython.ipaldap import ldap_initialize -@@ -1179,7 +1179,8 @@ def get_user_result(uid, givenname, sn, operation='show', omit=[], - initials=[givenname[0] + (sn or '')[:1]], - ipauniqueid=[fuzzy_uuid], - mepmanagedentry=[get_group_dn(uid)], -- objectclass=objectclasses.user, -+ objectclass=fuzzy_set_optional_oc( -+ objectclasses.user, 'ipantuserattrs'), - krbprincipalname=[u'%s@%s' % (uid, api.env.realm)], - krbcanonicalname=[u'%s@%s' % (uid, api.env.realm)], - ) --- -2.33.1 - - -From e3bc7bff2edd75f3cffe17177780dda4603cf956 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Tue, 28 Sep 2021 10:24:32 +0300 -Subject: [PATCH 18/26] ipa-kdb: store SID in the principal entry - -If the principal entry in LDAP has SID associated with it, store it to -be able to quickly assess the SID when processing PAC. - -Also rename string_to_sid to IPA-specific version as it uses different -prototype than Samba version. - -Fixes: https://pagure.io/freeipa/issue/9031 - -Signed-off-by: Alexander Bokovoy -Reviewed-by: Andreas Schneider -Reviewed-by: Robert Crittenden -(cherry picked from commit 4338c4ed8df804955c527e750ef4e082194ab58f) ---- - daemons/ipa-kdb/ipa_kdb.h | 7 ++++++ - daemons/ipa-kdb/ipa_kdb_mspac.c | 31 ++++++++++++++++++------- - daemons/ipa-kdb/ipa_kdb_mspac_private.h | 1 - - daemons/ipa-kdb/ipa_kdb_principals.c | 25 ++++++++++++++++++++ - daemons/ipa-kdb/tests/ipa_kdb_tests.c | 30 ++++++++++++------------ - 5 files changed, 69 insertions(+), 25 deletions(-) - -diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h -index 66a1d74f1..884dff950 100644 ---- a/daemons/ipa-kdb/ipa_kdb.h -+++ b/daemons/ipa-kdb/ipa_kdb.h -@@ -79,6 +79,7 @@ - #define IPA_USER_AUTH_TYPE "ipaUserAuthType" - - struct ipadb_mspac; -+struct dom_sid; - - enum ipadb_user_auth { - IPADB_USER_AUTH_NONE = 0, -@@ -155,6 +156,8 @@ struct ipadb_e_data { - bool has_tktpolaux; - enum ipadb_user_auth user_auth; - struct ipadb_e_pol_limits pol_limits[IPADB_USER_AUTH_IDX_MAX]; -+ bool has_sid; -+ struct dom_sid *sid; - }; - - struct ipadb_context *ipadb_get_context(krb5_context kcontext); -@@ -366,3 +369,7 @@ int ipadb_get_enc_salt_types(struct ipadb_context *ipactx, LDAPMessage *entry, - /* CERTAUTH PLUGIN */ - void ipa_certauth_free_moddata(krb5_certauth_moddata *moddata); - #endif -+ -+int ipadb_string_to_sid(const char *str, struct dom_sid *sid); -+void alloc_sid(struct dom_sid **sid); -+void free_sid(struct dom_sid **sid); -\ No newline at end of file -diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c -index 47b12a16f..f3e8657c2 100644 ---- a/daemons/ipa-kdb/ipa_kdb_mspac.c -+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c -@@ -80,7 +80,20 @@ static char *memberof_pac_attrs[] = { - #define AUTHZ_DATA_TYPE_PAD "PAD" - #define AUTHZ_DATA_TYPE_NONE "NONE" - --int string_to_sid(const char *str, struct dom_sid *sid) -+void alloc_sid(struct dom_sid **sid) -+{ -+ *sid = malloc(sizeof(struct dom_sid)); -+} -+ -+void free_sid(struct dom_sid **sid) -+{ -+ if (sid != NULL && *sid != NULL) { -+ free(*sid); -+ *sid = NULL; -+ } -+} -+ -+int ipadb_string_to_sid(const char *str, struct dom_sid *sid) - { - unsigned long val; - const char *s; -@@ -372,7 +385,7 @@ static krb5_error_code ipadb_add_asserted_identity(struct ipadb_context *ipactx, - - /* For S4U2Self, add Service Asserted Identity SID - * otherwise, add Authentication Authority Asserted Identity SID */ -- ret = string_to_sid((flags & KRB5_KDB_FLAG_PROTOCOL_TRANSITION) ? -+ ret = ipadb_string_to_sid((flags & KRB5_KDB_FLAG_PROTOCOL_TRANSITION) ? - "S-1-18-2" : "S-1-18-1", - arr[sidcount].sid); - if (ret) { -@@ -655,7 +668,7 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx, - /* SID is mandatory */ - return ret; - } -- ret = string_to_sid(strres, &sid); -+ ret = ipadb_string_to_sid(strres, &sid); - free(strres); - if (ret) { - return ret; -@@ -700,7 +713,7 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx, - } - } - if (strcasecmp(dval->type, "ipaNTSecurityIdentifier") == 0) { -- ret = string_to_sid((char *)dval->vals[0].bv_val, &gsid); -+ ret = ipadb_string_to_sid((char *)dval->vals[0].bv_val, &gsid); - if (ret) { - continue; - } -@@ -1189,7 +1202,7 @@ static int map_groups(TALLOC_CTX *memctx, krb5_context kcontext, - } - if (strcasecmp(dval->type, - "ipaNTSecurityIdentifier") == 0) { -- kerr = string_to_sid((char *)dval->vals[0].bv_val, &sid); -+ kerr = ipadb_string_to_sid((char *)dval->vals[0].bv_val, &sid); - if (kerr != 0) { - continue; - } -@@ -2434,7 +2447,7 @@ ipadb_adtrusts_fill_sid_blacklist(char **source_sid_blacklist, - } - - for (i = 0; i < len; i++) { -- (void) string_to_sid(source[i], &sid_blacklist[i]); -+ (void) ipadb_string_to_sid(source[i], &sid_blacklist[i]); - } - - *result_sids = sid_blacklist; -@@ -2594,7 +2607,7 @@ ipadb_mspac_get_trusted_domains(struct ipadb_context *ipactx) - goto done; - } - -- ret = string_to_sid(t[n].domain_sid, &t[n].domsid); -+ ret = ipadb_string_to_sid(t[n].domain_sid, &t[n].domsid); - if (ret && t[n].domain_sid != NULL) { - ret = EINVAL; - goto done; -@@ -2812,7 +2825,7 @@ krb5_error_code ipadb_reinit_mspac(struct ipadb_context *ipactx, bool force_rein - goto done; - } - -- ret = string_to_sid(resstr, &ipactx->mspac->domsid); -+ ret = ipadb_string_to_sid(resstr, &ipactx->mspac->domsid); - if (ret) { - kerr = ret; - free(resstr); -@@ -2865,7 +2878,7 @@ krb5_error_code ipadb_reinit_mspac(struct ipadb_context *ipactx, bool force_rein - goto done; - } - if (ret == 0) { -- ret = string_to_sid(resstr, &gsid); -+ ret = ipadb_string_to_sid(resstr, &gsid); - if (ret) { - free(resstr); - kerr = ret; -diff --git a/daemons/ipa-kdb/ipa_kdb_mspac_private.h b/daemons/ipa-kdb/ipa_kdb_mspac_private.h -index 8c8a3a001..3696c3c6c 100644 ---- a/daemons/ipa-kdb/ipa_kdb_mspac_private.h -+++ b/daemons/ipa-kdb/ipa_kdb_mspac_private.h -@@ -51,7 +51,6 @@ struct ipadb_adtrusts { - size_t *upn_suffixes_len; - }; - --int string_to_sid(const char *str, struct dom_sid *sid); - char *dom_sid_string(TALLOC_CTX *memctx, const struct dom_sid *dom_sid); - krb5_error_code filter_logon_info(krb5_context context, TALLOC_CTX *memctx, - krb5_data realm, struct PAC_LOGON_INFO_CTR *info); -diff --git a/daemons/ipa-kdb/ipa_kdb_principals.c b/daemons/ipa-kdb/ipa_kdb_principals.c -index 0a98ff054..15f3df4fe 100644 ---- a/daemons/ipa-kdb/ipa_kdb_principals.c -+++ b/daemons/ipa-kdb/ipa_kdb_principals.c -@@ -79,6 +79,8 @@ static char *std_principal_attrs[] = { - "ipatokenRadiusConfigLink", - "krbAuthIndMaxTicketLife", - "krbAuthIndMaxRenewableAge", -+ "ipaNTSecurityIdentifier", -+ "ipaUniqueID", - - "objectClass", - NULL -@@ -594,6 +596,7 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext, - char *restring; - char *uidstring; - char **authz_data_list; -+ char *princ_sid; - krb5_timestamp restime; - bool resbool; - int result; -@@ -963,6 +966,27 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext, - ipadb_parse_authind_policies(kcontext, lcontext, lentry, entry, ua); - } - -+ /* Add SID if it is associated with the principal account */ -+ ied->has_sid = false; -+ ied->sid = NULL; -+ ret = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry, -+ "ipaNTSecurityIdentifier", &princ_sid); -+ if (ret == 0 && princ_sid != NULL) { -+ alloc_sid(&ied->sid); -+ if (ied->sid == NULL) { -+ kerr = KRB5_KDB_INTERNAL_ERROR; -+ free(princ_sid); -+ goto done; -+ } -+ ret = ipadb_string_to_sid(princ_sid, ied->sid); -+ free(princ_sid); -+ if (ret != 0) { -+ kerr = ret; -+ goto done; -+ } -+ ied->has_sid = true; -+ } -+ - kerr = 0; - - done: -@@ -1568,6 +1592,7 @@ void ipadb_free_principal_e_data(krb5_context kcontext, krb5_octet *e_data) - } - free(ied->authz_data); - free(ied->pol); -+ free_sid(&ied->sid); - free(ied); - } - } -diff --git a/daemons/ipa-kdb/tests/ipa_kdb_tests.c b/daemons/ipa-kdb/tests/ipa_kdb_tests.c -index 0b51ffb96..d38dfd841 100644 ---- a/daemons/ipa-kdb/tests/ipa_kdb_tests.c -+++ b/daemons/ipa-kdb/tests/ipa_kdb_tests.c -@@ -105,7 +105,7 @@ static int setup(void **state) - /* make sure data is not read from LDAP */ - ipa_ctx->mspac->last_update = time(NULL) - 1; - -- ret = string_to_sid(DOM_SID, &ipa_ctx->mspac->domsid); -+ ret = ipadb_string_to_sid(DOM_SID, &ipa_ctx->mspac->domsid); - assert_int_equal(ret, 0); - - ipa_ctx->mspac->num_trusts = 1; -@@ -121,7 +121,7 @@ static int setup(void **state) - ipa_ctx->mspac->trusts[0].domain_sid = strdup(DOM_SID_TRUST); - assert_non_null(ipa_ctx->mspac->trusts[0].domain_sid); - -- ret = string_to_sid(DOM_SID_TRUST, &ipa_ctx->mspac->trusts[0].domsid); -+ ret = ipadb_string_to_sid(DOM_SID_TRUST, &ipa_ctx->mspac->trusts[0].domsid); - assert_int_equal(ret, 0); - - ipa_ctx->mspac->trusts[0].len_sid_blocklist_incoming = 1; -@@ -129,7 +129,7 @@ static int setup(void **state) - ipa_ctx->mspac->trusts[0].len_sid_blocklist_incoming, - sizeof(struct dom_sid)); - assert_non_null(ipa_ctx->mspac->trusts[0].sid_blocklist_incoming); -- ret = string_to_sid(BLOCKLIST_SID, -+ ret = ipadb_string_to_sid(BLOCKLIST_SID, - &ipa_ctx->mspac->trusts[0].sid_blocklist_incoming[0]); - assert_int_equal(ret, 0); - -@@ -216,7 +216,7 @@ static void test_filter_logon_info(void **state) - assert_int_equal(kerr, EINVAL); - - /* wrong domain SID */ -- ret = string_to_sid("S-1-5-21-1-1-1", &dom_sid); -+ ret = ipadb_string_to_sid("S-1-5-21-1-1-1", &dom_sid); - assert_int_equal(ret, 0); - info->info->info3.base.domain_sid = &dom_sid; - -@@ -224,7 +224,7 @@ static void test_filter_logon_info(void **state) - assert_int_equal(kerr, EINVAL); - - /* matching domain SID */ -- ret = string_to_sid(DOM_SID_TRUST, &dom_sid); -+ ret = ipadb_string_to_sid(DOM_SID_TRUST, &dom_sid); - assert_int_equal(ret, 0); - info->info->info3.base.domain_sid = &dom_sid; - -@@ -292,7 +292,7 @@ static void test_filter_logon_info(void **state) - } - - for (d = 0; d < info->info->info3.sidcount; d++) { -- ret = string_to_sid(test_data[c].sids[d], -+ ret = ipadb_string_to_sid(test_data[c].sids[d], - info->info->info3.sids[d].sid); - assert_int_equal(ret, 0); - } -@@ -434,7 +434,7 @@ static void test_get_authz_data_types(void **state) - krb5_free_principal(test_ctx->krb5_ctx, non_nfs_princ); - } - --static void test_string_to_sid(void **state) -+static void test_ipadb_string_to_sid(void **state) - { - int ret; - struct dom_sid sid; -@@ -442,25 +442,25 @@ static void test_string_to_sid(void **state) - {21, 2127521184, 1604012920, 1887927527, 72713, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}; - -- ret = string_to_sid(NULL, &sid); -+ ret = ipadb_string_to_sid(NULL, &sid); - assert_int_equal(ret, EINVAL); - -- ret = string_to_sid("abc", &sid); -+ ret = ipadb_string_to_sid("abc", &sid); - assert_int_equal(ret, EINVAL); - -- ret = string_to_sid("S-", &sid); -+ ret = ipadb_string_to_sid("S-", &sid); - assert_int_equal(ret, EINVAL); - -- ret = string_to_sid("S-ABC", &sid); -+ ret = ipadb_string_to_sid("S-ABC", &sid); - assert_int_equal(ret, EINVAL); - -- ret = string_to_sid("S-123", &sid); -+ ret = ipadb_string_to_sid("S-123", &sid); - assert_int_equal(ret, EINVAL); - -- ret = string_to_sid("S-1-123-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6", &sid); -+ ret = ipadb_string_to_sid("S-1-123-1-2-3-4-5-6-7-8-9-0-1-2-3-4-5-6", &sid); - assert_int_equal(ret, EINVAL); - -- ret = string_to_sid("S-1-5-21-2127521184-1604012920-1887927527-72713", -+ ret = ipadb_string_to_sid("S-1-5-21-2127521184-1604012920-1887927527-72713", - &sid); - assert_int_equal(ret, 0); - assert_memory_equal(&exp_sid, &sid, sizeof(struct dom_sid)); -@@ -531,7 +531,7 @@ int main(int argc, const char *argv[]) - setup, teardown), - cmocka_unit_test_setup_teardown(test_filter_logon_info, - setup, teardown), -- cmocka_unit_test(test_string_to_sid), -+ cmocka_unit_test(test_ipadb_string_to_sid), - cmocka_unit_test_setup_teardown(test_dom_sid_string, - setup, teardown), - cmocka_unit_test_setup_teardown(test_check_trusted_realms, --- -2.33.1 - - -From 5c5e5270b6a54df49a21e5b8796332440bb6269e Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Tue, 28 Sep 2021 10:26:30 +0300 -Subject: [PATCH 19/26] ipa-kdb: enforce SID checks when generating PAC - -Check that a domain SID and a user SID in the PAC passed to us are what -they should be for the local realm's principal. - -Fixes: https://pagure.io/freeipa/issue/9031 - -Signed-off-by: Alexander Bokovoy -Reviewed-by: Andreas Schneider -Reviewed-by: Robert Crittenden -(cherry picked from commit f81c8b89f0da45929208abbdfe5bd85b7ba41f90) ---- - daemons/ipa-kdb/ipa_kdb.h | 3 +- - daemons/ipa-kdb/ipa_kdb_mspac.c | 112 ++++++++++++++++++++++++++++---- - 2 files changed, 100 insertions(+), 15 deletions(-) - -diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h -index 884dff950..708e9545e 100644 ---- a/daemons/ipa-kdb/ipa_kdb.h -+++ b/daemons/ipa-kdb/ipa_kdb.h -@@ -372,4 +372,5 @@ void ipa_certauth_free_moddata(krb5_certauth_moddata *moddata); - - int ipadb_string_to_sid(const char *str, struct dom_sid *sid); - void alloc_sid(struct dom_sid **sid); --void free_sid(struct dom_sid **sid); -\ No newline at end of file -+void free_sid(struct dom_sid **sid); -+bool dom_sid_check(const struct dom_sid *sid1, const struct dom_sid *sid2, bool exact_check); -\ No newline at end of file -diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c -index f3e8657c2..59b77f5d8 100644 ---- a/daemons/ipa-kdb/ipa_kdb_mspac.c -+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c -@@ -236,7 +236,7 @@ static struct dom_sid *dom_sid_dup(TALLOC_CTX *memctx, - * dom_sid_check() is supposed to be used with sid1 representing domain SID - * and sid2 being either domain or resource SID in the domain - */ --static bool dom_sid_check(const struct dom_sid *sid1, const struct dom_sid *sid2, bool exact_check) -+bool dom_sid_check(const struct dom_sid *sid1, const struct dom_sid *sid2, bool exact_check) - { - int c, num; - -@@ -1404,6 +1404,82 @@ static void filter_logon_info_log_message_rid(struct dom_sid *sid, uint32_t rid) - } - } - -+static krb5_error_code check_logon_info_consistent(krb5_context context, -+ TALLOC_CTX *memctx, -+ krb5_const_principal client_princ, -+ struct PAC_LOGON_INFO_CTR *info) -+{ -+ krb5_error_code kerr = 0; -+ struct ipadb_context *ipactx; -+ bool result; -+ krb5_db_entry *client_actual = NULL; -+ struct ipadb_e_data *ied = NULL; -+ int flags = 0; -+#ifdef KRB5_KDB_FLAG_ALIAS_OK -+ flags = KRB5_KDB_FLAG_ALIAS_OK; -+#endif -+ -+ ipactx = ipadb_get_context(context); -+ if (!ipactx || !ipactx->mspac) { -+ return KRB5_KDB_DBNOTINITED; -+ } -+ -+ /* check exact sid */ -+ result = dom_sid_check(&ipactx->mspac->domsid, -+ info->info->info3.base.domain_sid, true); -+ if (!result) { -+ /* memctx is freed by the caller */ -+ char *sid = dom_sid_string(memctx, info->info->info3.base.domain_sid); -+ char *dom = dom_sid_string(memctx, &ipactx->mspac->domsid); -+ krb5_klog_syslog(LOG_ERR, "PAC issue: PAC record claims domain SID different " -+ "to local domain SID: local [%s], PAC [%s]", -+ dom ? dom : "", -+ sid ? sid : ""); -+ return KRB5KDC_ERR_POLICY; -+ } -+ -+ kerr = ipadb_get_principal(context, client_princ, flags, &client_actual); -+ if (kerr != 0) { -+ krb5_klog_syslog(LOG_ERR, "PAC issue: ipadb_get_principal failed."); -+ return KRB5KDC_ERR_POLICY; -+ } -+ -+ ied = (struct ipadb_e_data *)client_actual->e_data; -+ if (ied == NULL || ied->magic != IPA_E_DATA_MAGIC) { -+ krb5_klog_syslog(LOG_ERR, "PAC issue: client e_data fetching failed."); -+ kerr = EINVAL; -+ goto done; -+ } -+ -+ if (!ied->has_sid || ied->sid == NULL) { -+ /* Kerberos principal might have no SID associated in the DB entry. -+ * If this is host or service, we'll associate RID -515 or -516 in PAC -+ * depending on whether this is a domain member or domain controller -+ * but since this is not recorded in the DB entry, we the check for -+ * SID is not needed */ -+ goto done; -+ } -+ -+ result = dom_sid_check(ied->sid, info->info->info3.sids[0].sid, true); -+ if (!result) { -+ /* memctx is freed by the caller */ -+ char *local_sid = dom_sid_string(memctx, ied->sid); -+ char *pac_sid = dom_sid_string(memctx, info->info->info3.sids[0].sid); -+ krb5_klog_syslog(LOG_ERR, "PAC issue: client principal has a SID " -+ "different from what PAC claims. " -+ "local [%s] vs PAC [%s]", -+ local_sid ? local_sid : "", -+ pac_sid ? pac_sid : ""); -+ kerr = KRB5KDC_ERR_POLICY; -+ goto done; -+ } -+ -+done: -+ ipadb_free_principal(context, client_actual); -+ -+ return kerr; -+} -+ - krb5_error_code filter_logon_info(krb5_context context, - TALLOC_CTX *memctx, - krb5_data realm, -@@ -1631,12 +1707,14 @@ krb5_error_code filter_logon_info(krb5_context context, - - - static krb5_error_code ipadb_check_logon_info(krb5_context context, -- krb5_data origin_realm, -+ krb5_const_principal client_princ, -+ krb5_boolean is_cross_realm, - krb5_data *pac_blob) - { - struct PAC_LOGON_INFO_CTR info; - krb5_error_code kerr; - TALLOC_CTX *tmpctx; -+ krb5_data origin_realm = client_princ->realm; - - tmpctx = talloc_new(NULL); - if (!tmpctx) { -@@ -1648,6 +1726,13 @@ static krb5_error_code ipadb_check_logon_info(krb5_context context, - goto done; - } - -+ if (!is_cross_realm) { -+ /* For local realm case we need to check whether the PAC is for our user -+ * but we don't need to process further */ -+ kerr = check_logon_info_consistent(context, tmpctx, client_princ, &info); -+ goto done; -+ } -+ - kerr = filter_logon_info(context, tmpctx, origin_realm, &info); - if (kerr) { - goto done; -@@ -1873,19 +1958,18 @@ static krb5_error_code ipadb_verify_pac(krb5_context context, - goto done; - } - -- /* Now that the PAC is verified augment it with additional info if -- * it is coming from a different realm */ -- if (is_cross_realm) { -- kerr = krb5_pac_get_buffer(context, old_pac, -- KRB5_PAC_LOGON_INFO, &pac_blob); -- if (kerr != 0) { -- goto done; -- } -+ /* Now that the PAC is verified, do additional checks. -+ * Augment it with additional info if it is coming from a different realm */ -+ kerr = krb5_pac_get_buffer(context, old_pac, -+ KRB5_PAC_LOGON_INFO, &pac_blob); -+ if (kerr != 0) { -+ goto done; -+ } - -- kerr = ipadb_check_logon_info(context, client_princ->realm, &pac_blob); -- if (kerr != 0) { -- goto done; -- } -+ kerr = ipadb_check_logon_info(context, -+ client_princ, is_cross_realm, &pac_blob); -+ if (kerr != 0) { -+ goto done; - } - /* extract buffers and rebuilt pac from scratch so that when re-signing - * with a different cksum type does not cause issues due to mismatching --- -2.33.1 - - -From 3944307b68fe9f7710a0919a80f7acf9f6a10373 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Thu, 14 Oct 2021 11:28:02 +0300 -Subject: [PATCH 20/26] ipa-kdb: use entry DN to compare aliased entries in S4U - operations - -When working with aliased entries, we need a reliable way to detect -whether two principals reference the same database entry. This is -important in S4U checks. - -Ideally, we should be using SIDs for these checks as S4U requires PAC -record presence which cannot be issued without a SID associated with an -entry. This is true for user principals and a number of host/service -principals associated with Samba. Other service principals do not have -SIDs because we do not allocate POSIX IDs to them in FreeIPA. When PAC -is issued for these principals, they get SID of a domain computer or -domain controller depending on their placement (IPA client or IPA -server). - -Since 389-ds always returns unique entry DN for the same entry, rely on -this value instead. We could have used ipaUniqueID but for Kerberos -principals created through the KDB (kadmin/kdb5_util) we don't have -ipaUniqueID in the entry. - -Fixes: https://pagure.io/freeipa/issue/9031 - -Signed-off-by: Alexander Bokovoy -Reviewed-by: Rob Crittenden -(cherry picked from commit 98b9d6e9629b19b71f5429364d3abb54529e4d6e) ---- - daemons/ipa-kdb/ipa_kdb_delegation.c | 36 +++++++++++++++++++++++++++- - 1 file changed, 35 insertions(+), 1 deletion(-) - -diff --git a/daemons/ipa-kdb/ipa_kdb_delegation.c b/daemons/ipa-kdb/ipa_kdb_delegation.c -index 5ae5e0d9d..bfa344b9f 100644 ---- a/daemons/ipa-kdb/ipa_kdb_delegation.c -+++ b/daemons/ipa-kdb/ipa_kdb_delegation.c -@@ -21,6 +21,8 @@ - */ - - #include "ipa_kdb.h" -+#include -+#include - - static char *acl_attrs[] = { - "objectClass", -@@ -188,10 +190,41 @@ krb5_error_code ipadb_check_allowed_to_delegate(krb5_context kcontext, - const krb5_db_entry *server, - krb5_const_principal proxy) - { -- krb5_error_code kerr; -+ krb5_error_code kerr, result; - char *srv_principal = NULL; -+ krb5_db_entry *proxy_entry = NULL; -+ struct ipadb_e_data *ied_server, *ied_proxy; - LDAPMessage *res = NULL; - -+ /* Handle the case where server == proxy, this is allowed in S4U*/ -+ kerr = ipadb_get_principal(kcontext, proxy, -+ KRB5_KDB_FLAG_CLIENT_REFERRALS_ONLY, -+ &proxy_entry); -+ if (kerr) { -+ goto done; -+ } -+ -+ ied_server = (struct ipadb_e_data *) server->e_data; -+ ied_proxy = (struct ipadb_e_data *) proxy_entry->e_data; -+ -+ /* If we have SIDs for both entries, compare SIDs */ -+ if ((ied_server->has_sid && ied_server->sid != NULL) && -+ (ied_proxy->has_sid && ied_proxy->sid != NULL)) { -+ -+ if (dom_sid_check(ied_server->sid, ied_proxy->sid, true)) { -+ kerr = 0; -+ goto done; -+ } -+ } -+ -+ /* Otherwise, compare entry DNs */ -+ kerr = ulc_casecmp(ied_server->entry_dn, strlen(ied_server->entry_dn), -+ ied_proxy->entry_dn, strlen(ied_proxy->entry_dn), -+ NULL, NULL, &result); -+ if (kerr == 0 && result == 0) { -+ goto done; -+ } -+ - kerr = krb5_unparse_name(kcontext, server->princ, &srv_principal); - if (kerr) { - goto done; -@@ -208,6 +241,7 @@ krb5_error_code ipadb_check_allowed_to_delegate(krb5_context kcontext, - } - - done: -+ ipadb_free_principal(kcontext, proxy_entry); - krb5_free_unparsed_name(kcontext, srv_principal); - ldap_msgfree(res); - return kerr; --- -2.33.1 - - -From bab4a68635a51f8b4dd17f94993afe25a8682a8d Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Thu, 28 Oct 2021 11:01:08 +0300 -Subject: [PATCH 21/26] ipa-kdb: S4U2Proxy target should use a service name - without realm - -According to new Samba Kerberos tests and [MS-SFU] 3.2.5.2.4 -'KDC Replies with Service Ticket', the target should not include the -realm. - -Fixes: https://pagure.io/freeipa/issue/9031 - -Pair-programmed-with: Andreas Schneider -Signed-off-by: Alexander Bokovoy -Signed-off-by: Andreas Schneider -Reviewed-by: Rob Crittenden -(cherry picked from commit 5ae6261683fbd7d83982078397f4580a6663a0b1) ---- - daemons/ipa-kdb/ipa_kdb_mspac.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c -index 59b77f5d8..f729b9f2e 100644 ---- a/daemons/ipa-kdb/ipa_kdb_mspac.c -+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c -@@ -1847,7 +1847,10 @@ static krb5_error_code ipadb_add_transited_service(krb5_context context, - krb5_free_data_contents(context, &pac_blob); - memset(&pac_blob, 0, sizeof(krb5_data)); - -- kerr = krb5_unparse_name(context, proxy->princ, &tmpstr); -+ kerr = krb5_unparse_name_flags(context, proxy->princ, -+ KRB5_PRINCIPAL_UNPARSE_NO_REALM | -+ KRB5_PRINCIPAL_UNPARSE_DISPLAY, -+ &tmpstr); - if (kerr != 0) { - goto done; - } --- -2.33.1 - - -From 97bad0301b825442891baccf50082ba1b56a4de9 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Sat, 30 Oct 2021 10:08:34 +0300 -Subject: [PATCH 22/26] ipa-kdb: add support for PAC_UPN_DNS_INFO_EX - -CVE-2020-25721 mitigation: KDC must provide the new HAS_SAM_NAME_AND_SID -buffer with sAMAccountName and ObjectSID values associated with the -principal. - -The mitigation only works if NDR library supports the -PAC_UPN_DNS_INFO_EX buffer type. In case we cannot detect it at compile -time, a warning will be displayed at configure stage. - -Fixes: https://pagure.io/freeipa/issue/9031 - -Signed-off-by: Alexander Bokovoy -Reviewed-by: Rob Crittenden -(cherry picked from commit 933b958786f9c9d414a318ae1c10df8b9101e296) ---- - daemons/ipa-kdb/ipa_kdb_mspac.c | 41 +++++++++++++++++++++++++++++++-- - server.m4 | 7 ++++++ - 2 files changed, 46 insertions(+), 2 deletions(-) - -diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c -index f729b9f2e..75cb4f3b7 100644 ---- a/daemons/ipa-kdb/ipa_kdb_mspac.c -+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c -@@ -812,6 +812,25 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx, - return ret; - } - -+static krb5_error_code ipadb_get_sid_from_pac(TALLOC_CTX *ctx, -+ struct PAC_LOGON_INFO *info, -+ struct dom_sid *sid) -+{ -+ struct dom_sid *client_sid = NULL; -+ /* Construct SID from the PAC */ -+ if (info->info3.base.rid == 0) { -+ client_sid = info->info3.sids[0].sid; -+ } else { -+ client_sid = dom_sid_dup(ctx, info->info3.base.domain_sid); -+ if (!client_sid) { -+ return ENOMEM; -+ } -+ sid_append_rid(client_sid, info->info3.base.rid); -+ } -+ *sid = *client_sid; -+ return 0; -+} -+ - static krb5_error_code ipadb_get_pac(krb5_context kcontext, - krb5_db_entry *client, - unsigned int flags, -@@ -830,6 +849,7 @@ static krb5_error_code ipadb_get_pac(krb5_context kcontext, - enum ndr_err_code ndr_err; - union PAC_INFO pac_upn; - char *principal = NULL; -+ struct dom_sid client_sid; - - /* When no client entry is there, we cannot generate MS-PAC */ - if (!client) { -@@ -930,6 +950,18 @@ static krb5_error_code ipadb_get_pac(krb5_context kcontext, - pac_upn.upn_dns_info.flags |= PAC_UPN_DNS_FLAG_CONSTRUCTED; - } - -+ kerr = ipadb_get_sid_from_pac(tmpctx, pac_info.logon_info.info, &client_sid); -+ if (kerr) { -+ goto done; -+ } -+ -+#ifdef HAVE_PAC_UPN_DNS_INFO_EX -+ /* Add samAccountName and a SID */ -+ pac_upn.upn_dns_info.flags |= PAC_UPN_DNS_FLAG_HAS_SAM_NAME_AND_SID; -+ pac_upn.upn_dns_info.ex.sam_name_and_sid.samaccountname = pac_info.logon_info.info->info3.base.account_name.string; -+ pac_upn.upn_dns_info.ex.sam_name_and_sid.objectsid = &client_sid; -+#endif -+ - ndr_err = ndr_push_union_blob(&pac_data, tmpctx, &pac_upn, - PAC_TYPE_UPN_DNS_INFO, - (ndr_push_flags_fn_t)ndr_push_PAC_INFO); -@@ -1415,6 +1447,7 @@ static krb5_error_code check_logon_info_consistent(krb5_context context, - krb5_db_entry *client_actual = NULL; - struct ipadb_e_data *ied = NULL; - int flags = 0; -+ struct dom_sid client_sid; - #ifdef KRB5_KDB_FLAG_ALIAS_OK - flags = KRB5_KDB_FLAG_ALIAS_OK; - #endif -@@ -1460,11 +1493,15 @@ static krb5_error_code check_logon_info_consistent(krb5_context context, - goto done; - } - -- result = dom_sid_check(ied->sid, info->info->info3.sids[0].sid, true); -+ kerr = ipadb_get_sid_from_pac(memctx, info->info, &client_sid); -+ if (kerr) { -+ goto done; -+ } -+ result = dom_sid_check(ied->sid, &client_sid, true); - if (!result) { - /* memctx is freed by the caller */ - char *local_sid = dom_sid_string(memctx, ied->sid); -- char *pac_sid = dom_sid_string(memctx, info->info->info3.sids[0].sid); -+ char *pac_sid = dom_sid_string(memctx, &client_sid); - krb5_klog_syslog(LOG_ERR, "PAC issue: client principal has a SID " - "different from what PAC claims. " - "local [%s] vs PAC [%s]", -diff --git a/server.m4 b/server.m4 -index 3a2c3ae33..65c82d25a 100644 ---- a/server.m4 -+++ b/server.m4 -@@ -101,6 +101,13 @@ AC_CHECK_MEMBER( - [AC_MSG_NOTICE([struct PAC_DOMAIN_GROUP_MEMBERSHIP is not available])], - [[#include - #include ]]) -+AC_CHECK_MEMBER( -+ [struct PAC_UPN_DNS_INFO.ex], -+ [AC_DEFINE([HAVE_PAC_UPN_DNS_INFO_EX], [1], -+ [union PAC_UPN_DNS_INFO_EX is available.])], -+ [AC_MSG_NOTICE([union PAC_UPN_DNS_INFO_EX is not available, account protection is not active])], -+ [[#include -+ #include ]]) - - CFLAGS="$bck_cflags" - --- -2.33.1 - - -From b0371c4a3f591d42fe20c3ee1b3ad80de0a99089 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Sat, 30 Oct 2021 10:09:27 +0300 -Subject: [PATCH 23/26] ipa-kdb: add support for PAC_REQUESTER_SID buffer - -CVE-2020-25721 mitigation: KDC must provide the new PAC_REQUESTER_SID -buffer with ObjectSID value associated with the requester's principal. - -The mitigation only works if NDR library supports the PAC_REQUESTER_SID -buffer type. In case we cannot detect it at compile time, a warning will -be displayed at configure stage. - -Fixes: https://pagure.io/freeipa/issue/9031 - -Signed-off-by: Alexander Bokovoy -Reviewed-by: Rob Crittenden -(cherry picked from commit 1db8424858136675091f63054bafceaa96a9fdd8) ---- - daemons/ipa-kdb/ipa_kdb_mspac.c | 131 +++++++++++++++++++++++++++++++- - server.m4 | 7 ++ - 2 files changed, 134 insertions(+), 4 deletions(-) - -diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c -index 75cb4f3b7..ca6daccf1 100644 ---- a/daemons/ipa-kdb/ipa_kdb_mspac.c -+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c -@@ -812,6 +812,55 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx, - return ret; - } - -+#ifdef HAVE_PAC_REQUESTER_SID -+static krb5_error_code ipadb_get_requester_sid(krb5_context context, -+ krb5_pac pac, -+ struct dom_sid *sid) -+{ -+ enum ndr_err_code ndr_err; -+ krb5_error_code ret; -+ DATA_BLOB pac_requester_sid_in; -+ krb5_data k5pac_requester_sid_in; -+ union PAC_INFO info; -+ TALLOC_CTX *tmp_ctx; -+ struct ipadb_context *ipactx; -+ -+ ipactx = ipadb_get_context(context); -+ if (!ipactx) { -+ return KRB5_KDB_DBNOTINITED; -+ } -+ -+ tmp_ctx = talloc_new(NULL); -+ if (tmp_ctx == NULL) { -+ return ENOMEM; -+ } -+ -+ ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_REQUESTER_SID, -+ &k5pac_requester_sid_in); -+ if (ret != 0) { -+ talloc_free(tmp_ctx); -+ return ret; -+ } -+ -+ pac_requester_sid_in = data_blob_const(k5pac_requester_sid_in.data, -+ k5pac_requester_sid_in.length); -+ -+ ndr_err = ndr_pull_union_blob(&pac_requester_sid_in, tmp_ctx, &info, -+ PAC_TYPE_REQUESTER_SID, -+ (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO); -+ krb5_free_data_contents(context, &k5pac_requester_sid_in); -+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { -+ talloc_free(tmp_ctx); -+ return EINVAL; -+ } -+ -+ *sid = info.requester_sid.sid; -+ -+ talloc_free(tmp_ctx); -+ return 0; -+} -+#endif -+ - static krb5_error_code ipadb_get_sid_from_pac(TALLOC_CTX *ctx, - struct PAC_LOGON_INFO *info, - struct dom_sid *sid) -@@ -976,6 +1025,33 @@ static krb5_error_code ipadb_get_pac(krb5_context kcontext, - - kerr = krb5_pac_add_buffer(kcontext, *pac, KRB5_PAC_UPN_DNS_INFO, &data); - -+#ifdef HAVE_PAC_REQUESTER_SID -+ { -+ union PAC_INFO pac_requester_sid; -+ /* == Package PAC_REQUESTER_SID == */ -+ memset(&pac_requester_sid, 0, sizeof(pac_requester_sid)); -+ -+ pac_requester_sid.requester_sid.sid = client_sid; -+ -+ ndr_err = ndr_push_union_blob(&pac_data, tmpctx, &pac_requester_sid, -+ PAC_TYPE_REQUESTER_SID, -+ (ndr_push_flags_fn_t)ndr_push_PAC_INFO); -+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { -+ kerr = KRB5_KDB_INTERNAL_ERROR; -+ goto done; -+ } -+ -+ data.magic = KV5M_DATA; -+ data.data = (char *)pac_data.data; -+ data.length = pac_data.length; -+ -+ kerr = krb5_pac_add_buffer(kcontext, *pac, PAC_TYPE_REQUESTER_SID, &data); -+ if (kerr) { -+ goto done; -+ } -+ } -+#endif -+ - done: - ldap_msgfree(results); - talloc_free(tmpctx); -@@ -1457,7 +1533,19 @@ static krb5_error_code check_logon_info_consistent(krb5_context context, - return KRB5_KDB_DBNOTINITED; - } - -- /* check exact sid */ -+ /* We are asked to verify the PAC for our own principal, -+ * check that our own view on the PAC details is up to date */ -+ if (ipactx->mspac->domsid.num_auths == 0) { -+ /* Force re-init of KDB's view on our domain */ -+ kerr = ipadb_reinit_mspac(ipactx, true); -+ if (kerr != 0) { -+ krb5_klog_syslog(LOG_ERR, -+ "PAC issue: unable to update realm's view on PAC info"); -+ return KRB5KDC_ERR_POLICY; -+ } -+ } -+ -+ /* check exact domain SID */ - result = dom_sid_check(&ipactx->mspac->domsid, - info->info->info3.base.domain_sid, true); - if (!result) { -@@ -1466,7 +1554,7 @@ static krb5_error_code check_logon_info_consistent(krb5_context context, - char *dom = dom_sid_string(memctx, &ipactx->mspac->domsid); - krb5_klog_syslog(LOG_ERR, "PAC issue: PAC record claims domain SID different " - "to local domain SID: local [%s], PAC [%s]", -- dom ? dom : "", -+ dom ? dom : "", - sid ? sid : ""); - return KRB5KDC_ERR_POLICY; - } -@@ -1746,12 +1834,14 @@ krb5_error_code filter_logon_info(krb5_context context, - static krb5_error_code ipadb_check_logon_info(krb5_context context, - krb5_const_principal client_princ, - krb5_boolean is_cross_realm, -- krb5_data *pac_blob) -+ krb5_data *pac_blob, -+ struct dom_sid *requester_sid) - { - struct PAC_LOGON_INFO_CTR info; - krb5_error_code kerr; - TALLOC_CTX *tmpctx; - krb5_data origin_realm = client_princ->realm; -+ bool result; - - tmpctx = talloc_new(NULL); - if (!tmpctx) { -@@ -1763,6 +1853,28 @@ static krb5_error_code ipadb_check_logon_info(krb5_context context, - goto done; - } - -+ /* Check that requester SID is the same as in the PAC entry */ -+ if (requester_sid != NULL) { -+ struct dom_sid client_sid; -+ kerr = ipadb_get_sid_from_pac(tmpctx, info.info, &client_sid); -+ if (kerr) { -+ goto done; -+ } -+ result = dom_sid_check(&client_sid, requester_sid, true); -+ if (!result) { -+ /* memctx is freed by the caller */ -+ char *pac_sid = dom_sid_string(tmpctx, &client_sid); -+ char *req_sid = dom_sid_string(tmpctx, requester_sid); -+ krb5_klog_syslog(LOG_ERR, "PAC issue: PAC has a SID " -+ "different from what PAC requester claims. " -+ "PAC [%s] vs PAC requester [%s]", -+ pac_sid ? pac_sid : "", -+ req_sid ? req_sid : ""); -+ kerr = KRB5KDC_ERR_POLICY; -+ goto done; -+ } -+ } -+ - if (!is_cross_realm) { - /* For local realm case we need to check whether the PAC is for our user - * but we don't need to process further */ -@@ -1962,6 +2074,8 @@ static krb5_error_code ipadb_verify_pac(krb5_context context, - krb5_data pac_blob = { 0 , 0, NULL}; - bool is_cross_realm = false; - size_t i; -+ struct dom_sid *requester_sid = NULL; -+ struct dom_sid req_sid; - - kerr = krb5_pac_parse(context, - authdata[0]->contents, -@@ -2006,8 +2120,17 @@ static krb5_error_code ipadb_verify_pac(krb5_context context, - goto done; - } - -+ memset(&req_sid, '\0', sizeof(struct dom_sid)); -+#ifdef HAVE_PAC_REQUESTER_SID -+ kerr = ipadb_get_requester_sid(context, old_pac, &req_sid); -+ if (kerr == 0) { -+ requester_sid = &req_sid; -+ } -+#endif -+ - kerr = ipadb_check_logon_info(context, -- client_princ, is_cross_realm, &pac_blob); -+ client_princ, is_cross_realm, &pac_blob, -+ requester_sid); - if (kerr != 0) { - goto done; - } -diff --git a/server.m4 b/server.m4 -index 65c82d25a..648423dd4 100644 ---- a/server.m4 -+++ b/server.m4 -@@ -109,6 +109,13 @@ AC_CHECK_MEMBER( - [[#include - #include ]]) - -+AC_CHECK_MEMBER( -+ [struct PAC_REQUESTER_SID.sid], -+ [AC_DEFINE([HAVE_PAC_REQUESTER_SID], [1], -+ [struct PAC_REQUESTER_SID is available.])], -+ [AC_MSG_NOTICE([struct PAC_REQUESTER_SID is not available, account protection is not active])], -+ [[#include -+ #include ]]) - CFLAGS="$bck_cflags" - - LIBPDB_NAME="" --- -2.33.1 - - -From 3b64133bf5f1cecd219ada0d2ade09a6c8ff581c Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Sat, 30 Oct 2021 09:10:09 +0300 -Subject: [PATCH 24/26] ipa-kdb: add PAC_ATTRIBUTES_INFO PAC buffer support - -PAC_ATTRIBUTES_INFO PAC buffer allows both client and KDC to tell -whether a PAC structure was requested by the client or it was provided -by the KDC implicitly. Kerberos service then can continue processing or -deny access in case client explicitly requested to operate without PAC. - -Fixes: https://pagure.io/freeipa/issue/9031 - -Signed-off-by: Alexander Bokovoy -Signed-off-by: Andrew Bartlett -(cherry picked from commit ce4ac4265c4a4f1378ca2067d537bc8cc3c6a7c8) ---- - daemons/ipa-kdb/Makefile.am | 2 + - daemons/ipa-kdb/ipa_kdb_mspac.c | 143 ++++++++++++++++++++++++++++++++ - server.m4 | 8 ++ - 3 files changed, 153 insertions(+) - -diff --git a/daemons/ipa-kdb/Makefile.am b/daemons/ipa-kdb/Makefile.am -index 14c0546e0..5775d4086 100644 ---- a/daemons/ipa-kdb/Makefile.am -+++ b/daemons/ipa-kdb/Makefile.am -@@ -61,6 +61,7 @@ ipadb_la_LIBADD = \ - $(UNISTRING_LIBS) \ - $(SSSCERTMAP_LIBS) \ - $(top_builddir)/util/libutil.la \ -+ -lsamba-errors \ - $(NULL) - - if HAVE_CMOCKA -@@ -104,6 +105,7 @@ ipa_kdb_tests_LDADD = \ - -lkdb5 \ - -lsss_idmap \ - -lsamba-security-samba4 \ -+ -lsamba-errors \ - $(NULL) - - appdir = $(libexecdir)/ipa -diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c -index ca6daccf1..8a77a3538 100644 ---- a/daemons/ipa-kdb/ipa_kdb_mspac.c -+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c -@@ -880,6 +880,87 @@ static krb5_error_code ipadb_get_sid_from_pac(TALLOC_CTX *ctx, - return 0; - } - -+#ifdef HAVE_PAC_ATTRIBUTES_INFO -+static krb5_error_code ipadb_client_requested_pac(krb5_context context, -+ krb5_pac pac, -+ TALLOC_CTX *mem_ctx, -+ krb5_boolean *requested_pac) -+{ -+ enum ndr_err_code ndr_err; -+ krb5_data k5pac_attrs_in; -+ DATA_BLOB pac_attrs_in; -+ union PAC_INFO pac_attrs; -+ krb5_error_code ret; -+ -+ *requested_pac = true; -+ -+ ret = krb5_pac_get_buffer(context, pac, PAC_TYPE_ATTRIBUTES_INFO, -+ &k5pac_attrs_in); -+ if (ret != 0) { -+ return ret == ENOENT ? 0 : ret; -+ } -+ -+ pac_attrs_in = data_blob_const(k5pac_attrs_in.data, -+ k5pac_attrs_in.length); -+ -+ ndr_err = ndr_pull_union_blob(&pac_attrs_in, mem_ctx, &pac_attrs, -+ PAC_TYPE_ATTRIBUTES_INFO, -+ (ndr_pull_flags_fn_t)ndr_pull_PAC_INFO); -+ krb5_free_data_contents(context, &k5pac_attrs_in); -+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { -+ NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err); -+ krb5_klog_syslog(LOG_ERR, "can't parse the PAC ATTRIBUTES_INFO: %s\n", -+ nt_errstr(nt_status)); -+ return KRB5_KDB_INTERNAL_ERROR; -+ } -+ -+ if (pac_attrs.attributes_info.flags & (PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY -+ | PAC_ATTRIBUTE_FLAG_PAC_WAS_REQUESTED)) { -+ *requested_pac = true; -+ } else { -+ *requested_pac = false; -+ } -+ -+ return 0; -+} -+ -+static krb5_error_code ipadb_get_pac_attrs_blob(TALLOC_CTX *mem_ctx, -+ const krb5_boolean *pac_request, -+ DATA_BLOB *pac_attrs_data) -+{ -+ union PAC_INFO pac_attrs; -+ enum ndr_err_code ndr_err; -+ -+ memset(&pac_attrs, 0, sizeof(pac_attrs)); -+ -+ *pac_attrs_data = data_blob_null; -+ -+ /* Set the length of the flags in bits. */ -+ pac_attrs.attributes_info.flags_length = 2; -+ -+ if (pac_request == NULL) { -+ pac_attrs.attributes_info.flags -+ |= PAC_ATTRIBUTE_FLAG_PAC_WAS_GIVEN_IMPLICITLY; -+ } else if (*pac_request) { -+ pac_attrs.attributes_info.flags -+ |= PAC_ATTRIBUTE_FLAG_PAC_WAS_REQUESTED; -+ } -+ -+ ndr_err = ndr_push_union_blob(pac_attrs_data, mem_ctx, &pac_attrs, -+ PAC_TYPE_ATTRIBUTES_INFO, -+ (ndr_push_flags_fn_t)ndr_push_PAC_INFO); -+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { -+ NTSTATUS nt_status = ndr_map_error2ntstatus(ndr_err); -+ krb5_klog_syslog(LOG_ERR, "can't create PAC ATTRIBUTES_INFO: %s\n", -+ nt_errstr(nt_status)); -+ return KRB5_KDB_INTERNAL_ERROR; -+ } -+ -+ return 0; -+} -+ -+#endif -+ - static krb5_error_code ipadb_get_pac(krb5_context kcontext, - krb5_db_entry *client, - unsigned int flags, -@@ -1025,6 +1106,26 @@ static krb5_error_code ipadb_get_pac(krb5_context kcontext, - - kerr = krb5_pac_add_buffer(kcontext, *pac, KRB5_PAC_UPN_DNS_INFO, &data); - -+#ifdef HAVE_PAC_ATTRIBUTES_INFO -+ /* == Add implicit PAC type attributes info as we always try to generate PAC == */ -+ { -+ DATA_BLOB pac_attrs_data; -+ -+ kerr = ipadb_get_pac_attrs_blob(tmpctx, NULL, &pac_attrs_data); -+ if (kerr) { -+ goto done; -+ } -+ data.magic = KV5M_DATA; -+ data.data = (char *)pac_attrs_data.data; -+ data.length = pac_attrs_data.length; -+ -+ kerr = krb5_pac_add_buffer(kcontext, *pac, PAC_TYPE_ATTRIBUTES_INFO, &data); -+ if (kerr) { -+ goto done; -+ } -+ } -+#endif -+ - #ifdef HAVE_PAC_REQUESTER_SID - { - union PAC_INFO pac_requester_sid; -@@ -2165,6 +2266,48 @@ static krb5_error_code ipadb_verify_pac(krb5_context context, - continue; - } - -+#ifdef HAVE_PAC_ATTRIBUTES_INFO -+ if (types[i] == PAC_TYPE_ATTRIBUTES_INFO && -+ pac_blob.length != 0) { -+ /* == Check whether PAC was requested or given implicitly == */ -+ DATA_BLOB pac_attrs_data; -+ krb5_boolean pac_requested; -+ -+ TALLOC_CTX *tmpctx = talloc_new(NULL); -+ if (tmpctx == NULL) { -+ kerr = ENOMEM; -+ krb5_pac_free(context, new_pac); -+ goto done; -+ } -+ -+ kerr = ipadb_client_requested_pac(context, old_pac, tmpctx, &pac_requested); -+ if (kerr != 0) { -+ talloc_free(tmpctx); -+ krb5_pac_free(context, new_pac); -+ goto done; -+ } -+ -+ kerr = ipadb_get_pac_attrs_blob(tmpctx, &pac_requested, &pac_attrs_data); -+ if (kerr) { -+ talloc_free(tmpctx); -+ krb5_pac_free(context, new_pac); -+ goto done; -+ } -+ data.magic = KV5M_DATA; -+ data.data = (char *)pac_attrs_data.data; -+ data.length = pac_attrs_data.length; -+ -+ kerr = krb5_pac_add_buffer(context, new_pac, PAC_TYPE_ATTRIBUTES_INFO, &data); -+ if (kerr) { -+ talloc_free(tmpctx); -+ krb5_pac_free(context, new_pac); -+ goto done; -+ } -+ -+ continue; -+ } -+#endif -+ - if (types[i] == KRB5_PAC_DELEGATION_INFO && - (flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION)) { - /* skip it here, we will add it explicitly later */ -diff --git a/server.m4 b/server.m4 -index 648423dd4..5a14af06a 100644 ---- a/server.m4 -+++ b/server.m4 -@@ -116,6 +116,14 @@ AC_CHECK_MEMBER( - [AC_MSG_NOTICE([struct PAC_REQUESTER_SID is not available, account protection is not active])], - [[#include - #include ]]) -+ -+AC_CHECK_MEMBER( -+ [struct PAC_ATTRIBUTES_INFO.flags], -+ [AC_DEFINE([HAVE_PAC_ATTRIBUTES_INFO], [1], -+ [struct PAC_ATTRIBUTES_INFO is available.])], -+ [AC_MSG_NOTICE([struct PAC_ATTRIBUTES_INFO is not available, account protection is not active])], -+ [[#include -+ #include ]]) - CFLAGS="$bck_cflags" - - LIBPDB_NAME="" --- -2.33.1 - - -From 151cf41c4fdf3d7b34890a6e571ba6ccb89dc87b Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Fri, 29 Oct 2021 22:30:53 +0300 -Subject: [PATCH 25/26] ipa-kdb: Use proper account flags for Kerberos - principal in PAC - -As part of CVE-2020-25717 mitigations, Samba expects correct user -account flags in the PAC. This means for services and host principals we -should be using ACB_WSTRUST or ACB_SVRTRUST depending on whether they -run on IPA clients ("workstation" or "domain member") or IPA servers -("domain controller"). - -Fixes: https://pagure.io/freeipa/issue/9031 - -Signed-off-by: Alexander Bokovoy -(cherry picked from commit f14df66cc2b4deece440e42b265f38ede207a5d6) ---- - daemons/ipa-kdb/ipa_kdb_mspac.c | 19 +++++++++++++++---- - 1 file changed, 15 insertions(+), 4 deletions(-) - -diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c -index 8a77a3538..0e0ee3616 100644 ---- a/daemons/ipa-kdb/ipa_kdb_mspac.c -+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c -@@ -648,6 +648,11 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx, - info3->base.logon_count = 0; /* we do not have this info yet */ - info3->base.bad_password_count = 0; /* we do not have this info yet */ - -+ /* Use AES keys by default to detect changes. -+ * This bit is not used by Windows clients and servers so we can -+ * clear it after detecting the changes */ -+ info3->base.acct_flags = ACB_USE_AES_KEYS; -+ - if ((is_host || is_service)) { - /* it is either host or service, so get the hostname first */ - char *sep = strchr(info3->base.account_name.string, '/'); -@@ -655,11 +660,13 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx, - ipactx, - sep ? sep + 1 : info3->base.account_name.string); - if (is_master) { -- /* Well know RID of domain controllers group */ -+ /* Well known RID of domain controllers group */ - info3->base.rid = 516; -+ info3->base.acct_flags |= ACB_SVRTRUST; - } else { -- /* Well know RID of domain computers group */ -+ /* Well known RID of domain computers group */ - info3->base.rid = 515; -+ info3->base.acct_flags |= ACB_WSTRUST; - } - } else { - ret = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry, -@@ -799,9 +806,13 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx, - /* always zero out, not used for Krb, only NTLM */ - memset(&info3->base.LMSessKey, '\0', sizeof(info3->base.LMSessKey)); - -- /* TODO: fill based on objectclass, user vs computer, etc... */ -- info3->base.acct_flags = ACB_NORMAL; /* samr_AcctFlags */ -+ /* If account type was not set before, default to ACB_NORMAL */ -+ if (!(info3->base.acct_flags & ~ACB_USE_AES_KEYS)) { -+ info3->base.acct_flags |= ACB_NORMAL; /* samr_AcctFlags */ -+ } - -+ /* Clear ACB_USE_AES_KEYS as it is not used by Windows */ -+ info3->base.acct_flags &= ~ACB_USE_AES_KEYS; - info3->base.sub_auth_status = 0; - info3->base.last_successful_logon = 0; - info3->base.last_failed_logon = 0; --- -2.33.1 - - -From 12ace6563444226dcd52a65ae3cd248fcaa29d5b Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Sat, 30 Oct 2021 10:49:37 +0300 -Subject: [PATCH 26/26] SMB: switch IPA domain controller role - -As a part of CVE-2020-25717 mitigations, Samba now assumes 'CLASSIC -PRIMARY DOMAIN CONTROLLER' server role does not support Kerberos -operations. This is the role that IPA domain controller was using for -its hybrid NT4/AD-like operation. - -Instead, 'IPA PRIMARY DOMAIN CONTROLLER' server role was introduced in -Samba. Switch to this role for new installations and during the upgrade -of servers running ADTRUST role. - -Fixes: https://pagure.io/freeipa/issue/9031 - -Signed-off-by: Alexander Bokovoy -Reviewed-by: Rob Crittenden -(cherry picked from commit cae0633a7488ea8ed1aea6a2d74b31b0e4ea2068) ---- - install/share/smb.conf.registry.template | 2 +- - ipaserver/install/adtrustinstance.py | 14 +++++++++++++- - ipaserver/install/server/upgrade.py | 15 +++++++++++++++ - 3 files changed, 29 insertions(+), 2 deletions(-) - -diff --git a/install/share/smb.conf.registry.template b/install/share/smb.conf.registry.template -index c55a0c307..1d1d12161 100644 ---- a/install/share/smb.conf.registry.template -+++ b/install/share/smb.conf.registry.template -@@ -5,7 +5,7 @@ realm = $REALM - kerberos method = dedicated keytab - dedicated keytab file = /etc/samba/samba.keytab - create krb5 conf = no --server role = CLASSIC PRIMARY DOMAIN CONTROLLER -+server role = $SERVER_ROLE - security = user - domain master = yes - domain logons = yes -diff --git a/ipaserver/install/adtrustinstance.py b/ipaserver/install/adtrustinstance.py -index af5c14a7e..e9a523f4d 100644 ---- a/ipaserver/install/adtrustinstance.py -+++ b/ipaserver/install/adtrustinstance.py -@@ -146,6 +146,8 @@ class ADTRUSTInstance(service.Service): - OBJC_GROUP = "ipaNTGroupAttrs" - OBJC_DOMAIN = "ipaNTDomainAttrs" - FALLBACK_GROUP_NAME = u'Default SMB Group' -+ SERVER_ROLE_OLD = "CLASSIC PRIMARY DOMAIN CONTROLLER" -+ SERVER_ROLE_NEW = "IPA PRIMARY DOMAIN CONTROLLER" - - def __init__(self, fstore=None, fulltrust=True): - self.netbios_name = None -@@ -573,7 +575,16 @@ class ADTRUSTInstance(service.Service): - with tempfile.NamedTemporaryFile(mode='w') as tmp_conf: - tmp_conf.write(conf) - tmp_conf.flush() -- ipautil.run([paths.NET, "conf", "import", tmp_conf.name]) -+ try: -+ ipautil.run([paths.NET, "conf", "import", tmp_conf.name]) -+ except ipautil.CalledProcessError as e: -+ if e.returncode == 255: -+ # We have old Samba that doesn't support IPA DC server role -+ # re-try again with the older variant, upgrade code will -+ # take care to change the role later when Samba is upgraded -+ # as well. -+ self.sub_dict['SERVER_ROLE'] = self.SERVER_ROLE_OLD -+ self.__write_smb_registry() - - def __map_Guests_to_nobody(self): - map_Guests_to_nobody() -@@ -775,6 +786,7 @@ class ADTRUSTInstance(service.Service): - LDAPI_SOCKET=self.ldapi_socket, - FQDN=self.fqdn, - SAMBA_DIR=paths.SAMBA_DIR, -+ SERVER_ROLE=self.SERVER_ROLE_NEW, - ) - - def setup(self, fqdn, realm_name, netbios_name, -diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py -index 942a8e106..5be5f73ba 100644 ---- a/ipaserver/install/server/upgrade.py -+++ b/ipaserver/install/server/upgrade.py -@@ -358,6 +358,21 @@ def upgrade_adtrust_config(): - else: - logger.warning("Error updating Samba registry: %s", e) - -+ logger.info("[Change 'server role' from " -+ "'CLASSIC PRIMARY DOMAIN CONTROLLER' " -+ "to 'IPA PRIMARY DOMAIN CONTROLLER' in Samba configuration]") -+ -+ args = [paths.NET, "conf", "setparm", "global", -+ "server role", "IPA PRIMARY DOMAIN CONTROLLER"] -+ -+ try: -+ ipautil.run(args) -+ except ipautil.CalledProcessError as e: -+ # Only report an error if return code is not 255 -+ # which indicates that the new server role is not supported -+ # and we don't need to do anything -+ if e.returncode != 255: -+ logger.warning("Error updating Samba registry: %s", e) - - def ca_configure_profiles_acl(ca): - logger.info('[Authorizing RA Agent to modify profiles]') --- -2.33.1 -