diff --git a/.gitignore b/.gitignore index a08d1d6..5471ecd 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/freeipa-4.9.11.tar.gz +SOURCES/freeipa-4.9.12.tar.gz diff --git a/.ipa.metadata b/.ipa.metadata index f1dac03..de73ab5 100644 --- a/.ipa.metadata +++ b/.ipa.metadata @@ -1 +1 @@ -4ef188d43f5f2a09e214dd2bae68595a5977bb61 SOURCES/freeipa-4.9.11.tar.gz +ea6c8a209748b4ad8d07da556f705a366b3dd6c1 SOURCES/freeipa-4.9.12.tar.gz diff --git a/SOURCES/0001-updates-fix-memberManager-ACI-to-allow-managers-from-a-specified-group_rhbz#2056009.patch b/SOURCES/0001-updates-fix-memberManager-ACI-to-allow-managers-from-a-specified-group_rhbz#2056009.patch deleted file mode 100644 index ecbb24f..0000000 --- a/SOURCES/0001-updates-fix-memberManager-ACI-to-allow-managers-from-a-specified-group_rhbz#2056009.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 651e28c1fb6b86ad1fbd4ea98644e00b7042499c Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Dec 02 2022 12:21:22 +0000 -Subject: updates: fix memberManager ACI to allow managers from a specified group - - -The original implementation of the member manager added support for both -user and group managers but left out upgrade scenario. This means when -upgrading existing installation a manager whose rights defined by the -group membership would not be able to add group members until the ACI is -fixed. - -Remove old ACI and add a full one during upgrade step. - -Fixes: https://pagure.io/freeipa/issue/9286 -Signed-off-by: Alexander Bokovoy -Reviewed-By: Florence Blanc-Renaud - ---- - -diff --git a/install/updates/20-aci.update b/install/updates/20-aci.update -index a168bb9..4a7ba13 100644 ---- a/install/updates/20-aci.update -+++ b/install/updates/20-aci.update -@@ -141,11 +141,13 @@ add:aci:(targetattr = "usercertificate")(version 3.0;acl "selfservice:Users can - - # Allow member managers to modify members of user groups - dn: cn=groups,cn=accounts,$SUFFIX --add:aci: (targetattr = "member")(targetfilter = "(objectclass=ipaUserGroup)")(version 3.0; acl "Allow member managers to modify members of user groups"; allow (write) userattr = "memberManager#USERDN";) -+remove:aci: (targetattr = "member")(targetfilter = "(objectclass=ipaUserGroup)")(version 3.0; acl "Allow member managers to modify members of user groups"; allow (write) userattr = "memberManager#USERDN";) -+add:aci: (targetattr = "member")(targetfilter = "(objectclass=ipaUserGroup)")(version 3.0; acl "Allow member managers to modify members of user groups"; allow (write) userattr = "memberManager#USERDN" or userattr = "memberManager#GROUPDN";) - - # Allow member managers to modify members of host groups - dn: cn=hostgroups,cn=accounts,$SUFFIX --add:aci: (targetattr = "member")(targetfilter = "(objectclass=ipaHostGroup)")(version 3.0; acl "Allow member managers to modify members of host groups"; allow (write) userattr = "memberManager#USERDN";) -+remove:aci: (targetattr = "member")(targetfilter = "(objectclass=ipaHostGroup)")(version 3.0; acl "Allow member managers to modify members of host groups"; allow (write) userattr = "memberManager#USERDN";) -+add:aci: (targetattr = "member")(targetfilter = "(objectclass=ipaHostGroup)")(version 3.0; acl "Allow member managers to modify members of host groups"; allow (write) userattr = "memberManager#USERDN" or userattr = "memberManager#GROUPDN";) - - # Hosts can add and delete their own services - dn: cn=services,cn=accounts,$SUFFIX - diff --git a/SOURCES/0001-user-or-group-name-explain-the-supported-format_rhbz#2150217.patch b/SOURCES/0001-user-or-group-name-explain-the-supported-format_rhbz#2150217.patch new file mode 100644 index 0000000..8bad0c6 --- /dev/null +++ b/SOURCES/0001-user-or-group-name-explain-the-supported-format_rhbz#2150217.patch @@ -0,0 +1,261 @@ +From f42a106e84c1fd609350da2540289ce945a7ecbd Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Thu, 11 May 2023 10:53:58 +0200 +Subject: [PATCH] user or group name: explain the supported format + +The commands ipa user-add or ipa group-add validate the +format of the user/group name and display the following +message when it does not conform to the expectations: +invalid 'login': may only include letters, numbers, _, -, . and $ + +The format is more complex, for instance '1234567' is an invalid +user name but the failure is inconsistent with the error message. +Modify the error message to point to ipa help user/group and add +more details in the help message. + +Same change for idoverrideuser and idoverridegroup: +The user/group name must follow these rules: +- cannot contain only numbers +- must start with a letter, a number, _ or . +- may contain letters, numbers, _, ., or - +- may end with a letter, a number, _, ., - or $ + +Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2150217 + +Signed-off-by: Florence Blanc-Renaud +Reviewed-By: Rafael Guterres Jeffman +Reviewed-By: Alexander Bokovoy +Reviewed-By: Rob Crittenden +--- + ipalib/constants.py | 5 +++++ + ipaserver/plugins/baseuser.py | 2 +- + ipaserver/plugins/group.py | 10 ++++++++-- + ipaserver/plugins/idviews.py | 5 +++-- + ipaserver/plugins/stageuser.py | 6 ++++++ + ipaserver/plugins/user.py | 6 ++++++ + ipatests/test_xmlrpc/test_group_plugin.py | 5 +++-- + ipatests/test_xmlrpc/test_stageuser_plugin.py | 3 ++- + ipatests/test_xmlrpc/test_user_plugin.py | 7 ++++--- + 9 files changed, 38 insertions(+), 11 deletions(-) + +diff --git a/ipalib/constants.py b/ipalib/constants.py +index 4b759a573..104419bc2 100644 +--- a/ipalib/constants.py ++++ b/ipalib/constants.py +@@ -319,6 +319,11 @@ MAXHOSTFQDNLEN = 253 + PATTERN_GROUPUSER_NAME = ( + '(?!^[0-9]+$)^[a-zA-Z0-9_.][a-zA-Z0-9_.-]*[a-zA-Z0-9_.$-]?$' + ) ++ERRMSG_GROUPUSER_NAME = ( ++ 'may only include letters, numbers, _, -, . and $' ++ ', refer to \'ipa help {}\' for complete format ' ++ 'description' ++) + + # Kerberos Anonymous principal name + ANON_USER = 'WELLKNOWN/ANONYMOUS' +diff --git a/ipaserver/plugins/baseuser.py b/ipaserver/plugins/baseuser.py +index 684a65242..bae6c54ff 100644 +--- a/ipaserver/plugins/baseuser.py ++++ b/ipaserver/plugins/baseuser.py +@@ -211,7 +211,7 @@ class baseuser(LDAPObject): + takes_params = ( + Str('uid', + pattern=constants.PATTERN_GROUPUSER_NAME, +- pattern_errmsg='may only include letters, numbers, _, -, . and $', ++ pattern_errmsg=constants.ERRMSG_GROUPUSER_NAME.format('user'), + maxlength=255, + cli_name='login', + label=_('User login'), +diff --git a/ipaserver/plugins/group.py b/ipaserver/plugins/group.py +index afdad93c1..0333ed622 100644 +--- a/ipaserver/plugins/group.py ++++ b/ipaserver/plugins/group.py +@@ -24,7 +24,7 @@ import logging + + from ipalib import api + from ipalib import Int, Str, Flag +-from ipalib.constants import PATTERN_GROUPUSER_NAME ++from ipalib.constants import PATTERN_GROUPUSER_NAME, ERRMSG_GROUPUSER_NAME + from ipalib.plugable import Registry + from .baseldap import ( + add_external_post_callback, +@@ -70,6 +70,12 @@ converted to non-POSIX groups. + + Every group must have a description. + ++The group name must follow these rules: ++- cannot contain only numbers ++- must start with a letter, a number, _ or . ++- may contain letters, numbers, _, ., or - ++- may end with a letter, a number, _, ., - or $ ++ + POSIX groups must have a Group ID (GID) number. Changing a GID is + supported but can have an impact on your file permissions. It is not necessary + to supply a GID when creating a group. IPA will generate one automatically +@@ -330,7 +336,7 @@ class group(LDAPObject): + takes_params = ( + Str('cn', + pattern=PATTERN_GROUPUSER_NAME, +- pattern_errmsg='may only include letters, numbers, _, -, . and $', ++ pattern_errmsg=ERRMSG_GROUPUSER_NAME.format('group'), + maxlength=255, + cli_name='group_name', + label=_('Group name'), +diff --git a/ipaserver/plugins/idviews.py b/ipaserver/plugins/idviews.py +index 4f4b3a2f7..6a16884cf 100644 +--- a/ipaserver/plugins/idviews.py ++++ b/ipaserver/plugins/idviews.py +@@ -37,6 +37,7 @@ from ipalib.constants import ( + IPA_ANCHOR_PREFIX, + SID_ANCHOR_PREFIX, + PATTERN_GROUPUSER_NAME, ++ ERRMSG_GROUPUSER_NAME + ) + from ipalib.plugable import Registry + from ipalib.util import (normalize_sshpubkey, validate_sshpubkey, +@@ -1025,7 +1026,7 @@ class idoverrideuser(baseidoverride): + takes_params = baseidoverride.takes_params + ( + Str('uid?', + pattern=PATTERN_GROUPUSER_NAME, +- pattern_errmsg='may only include letters, numbers, _, -, . and $', ++ pattern_errmsg=ERRMSG_GROUPUSER_NAME.format('user'), + maxlength=255, + cli_name='login', + label=_('User login'), +@@ -1128,7 +1129,7 @@ class idoverridegroup(baseidoverride): + takes_params = baseidoverride.takes_params + ( + Str('cn?', + pattern=PATTERN_GROUPUSER_NAME, +- pattern_errmsg='may only include letters, numbers, _, -, . and $', ++ pattern_errmsg=ERRMSG_GROUPUSER_NAME.format('group'), + maxlength=255, + cli_name='group_name', + label=_('Group name'), +diff --git a/ipaserver/plugins/stageuser.py b/ipaserver/plugins/stageuser.py +index 760dff7ab..51438a83a 100644 +--- a/ipaserver/plugins/stageuser.py ++++ b/ipaserver/plugins/stageuser.py +@@ -94,6 +94,12 @@ usernames that start with a digit or usernames that exceed a certain length + may cause problems for some UNIX systems. + Use 'ipa config-mod' to change the username format allowed by IPA tools. + ++The user name must follow these rules: ++- cannot contain only numbers ++- must start with a letter, a number, _ or . ++- may contain letters, numbers, _, ., or - ++- may end with a letter, a number, _, ., - or $ ++ + + EXAMPLES: + +diff --git a/ipaserver/plugins/user.py b/ipaserver/plugins/user.py +index fa8a67d3d..643b44f14 100644 +--- a/ipaserver/plugins/user.py ++++ b/ipaserver/plugins/user.py +@@ -88,6 +88,12 @@ usernames that start with a digit or usernames that exceed a certain length + may cause problems for some UNIX systems. + Use 'ipa config-mod' to change the username format allowed by IPA tools. + ++The user name must follow these rules: ++- cannot contain only numbers ++- must start with a letter, a number, _ or . ++- may contain letters, numbers, _, ., or - ++- may end with a letter, a number, _, ., - or $ ++ + Disabling a user account prevents that user from obtaining new Kerberos + credentials. It does not invalidate any credentials that have already + been issued. +diff --git a/ipatests/test_xmlrpc/test_group_plugin.py b/ipatests/test_xmlrpc/test_group_plugin.py +index f9a0e2cfe..27bc21fbc 100644 +--- a/ipatests/test_xmlrpc/test_group_plugin.py ++++ b/ipatests/test_xmlrpc/test_group_plugin.py +@@ -25,6 +25,7 @@ Test the `ipaserver/plugins/group.py` module. + import pytest + + from ipalib import errors ++from ipalib.constants import ERRMSG_GROUPUSER_NAME + from ipatests.test_xmlrpc import objectclasses + from ipatests.test_xmlrpc.xmlrpc_test import ( + fuzzy_digits, fuzzy_uuid, fuzzy_set_ci, +@@ -169,7 +170,7 @@ class TestGroup(XMLRPC_test): + ) + with raises_exact(errors.ValidationError( + name='group_name', +- error=u'may only include letters, numbers, _, -, . and $')): ++ error=ERRMSG_GROUPUSER_NAME.format('group'))): + command() + + def test_create_with_name_starting_with_numeric(self): +@@ -188,7 +189,7 @@ class TestGroup(XMLRPC_test): + ) + with raises_exact(errors.ValidationError( + name='group_name', +- error=u'may only include letters, numbers, _, -, . and $', ++ error=ERRMSG_GROUPUSER_NAME.format('group'), + )): + testgroup.create() + +diff --git a/ipatests/test_xmlrpc/test_stageuser_plugin.py b/ipatests/test_xmlrpc/test_stageuser_plugin.py +index fd146876c..bd877aa94 100644 +--- a/ipatests/test_xmlrpc/test_stageuser_plugin.py ++++ b/ipatests/test_xmlrpc/test_stageuser_plugin.py +@@ -12,6 +12,7 @@ import six + + from collections import OrderedDict + from ipalib import api, errors ++from ipalib.constants import ERRMSG_GROUPUSER_NAME + from ipaplatform.constants import constants as platformconstants + + from ipatests.test_xmlrpc.xmlrpc_test import XMLRPC_test, raises_exact +@@ -357,7 +358,7 @@ class TestCreateInvalidAttributes(XMLRPC_test): + command = invalid.make_create_command() + with raises_exact(errors.ValidationError( + name='login', +- error=u"may only include letters, numbers, _, -, . and $")): ++ error=ERRMSG_GROUPUSER_NAME.format('user'))): + command() + + def test_create_long_uid(self): +diff --git a/ipatests/test_xmlrpc/test_user_plugin.py b/ipatests/test_xmlrpc/test_user_plugin.py +index c156a8793..eadfe6a65 100644 +--- a/ipatests/test_xmlrpc/test_user_plugin.py ++++ b/ipatests/test_xmlrpc/test_user_plugin.py +@@ -31,6 +31,7 @@ import ldap + import re + + from ipalib import api, errors ++from ipalib.constants import ERRMSG_GROUPUSER_NAME + from ipaplatform.constants import constants as platformconstants + from ipapython import ipautil + from ipatests.test_xmlrpc import objectclasses +@@ -502,7 +503,7 @@ class TestUpdate(XMLRPC_test): + ) + with raises_exact(errors.ValidationError( + name='rename', +- error=u'may only include letters, numbers, _, -, . and $')): ++ error=ERRMSG_GROUPUSER_NAME.format('user'))): + command() + + def test_add_radius_username(self, user): +@@ -556,7 +557,7 @@ class TestCreate(XMLRPC_test): + command = testuser.make_create_command() + with raises_exact(errors.ValidationError( + name=u'login', +- error=u'may only include letters, numbers, _, -, . and $')): ++ error=ERRMSG_GROUPUSER_NAME.format('user'))): + command() + + def test_create_with_too_long_login(self): +@@ -730,7 +731,7 @@ class TestCreate(XMLRPC_test): + ) + with raises_exact(errors.ValidationError( + name=u'login', +- error=u'may only include letters, numbers, _, -, . and $', ++ error=ERRMSG_GROUPUSER_NAME.format('user'), + )): + testuser.create() + +-- +2.40.1 + diff --git a/SOURCES/0002-Use-the-python-cryptography-parser-directly-in-cert-find_rhbz#2164349.patch b/SOURCES/0002-Use-the-python-cryptography-parser-directly-in-cert-find_rhbz#2164349.patch new file mode 100644 index 0000000..7fc5737 --- /dev/null +++ b/SOURCES/0002-Use-the-python-cryptography-parser-directly-in-cert-find_rhbz#2164349.patch @@ -0,0 +1,242 @@ +From 9fe30f21c987bdccf80ef5f6d645fdc59b393bdb Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Jun 16 2023 19:09:52 +0000 +Subject: Revert "Use the OpenSSL certificate parser in cert-find" + + +This reverts commit 191880bc9f77c3e8a3cecc82e6eea33ab5ad03e4. + +The problem isn't with python-cryptography, it is with the +IPACertificate class which does way more work on a certificate +than is necessary in cert-find. + +Related: https://pagure.io/freeipa/issue/9331 +Reviewed-By: Florence Blanc-Renaud + +--- + +diff --git a/freeipa.spec.in b/freeipa.spec.in +index f3380b4..2b18963 100755 +--- a/freeipa.spec.in ++++ b/freeipa.spec.in +@@ -390,7 +390,6 @@ BuildRequires: python3-pylint + BuildRequires: python3-pytest-multihost + BuildRequires: python3-pytest-sourceorder + BuildRequires: python3-qrcode-core >= 5.0.0 +-BuildRequires: python3-pyOpenSSL + BuildRequires: python3-samba + BuildRequires: python3-six + BuildRequires: python3-sss +@@ -862,7 +861,6 @@ Requires: python3-netifaces >= 0.10.4 + Requires: python3-pyasn1 >= 0.3.2-2 + Requires: python3-pyasn1-modules >= 0.3.2-2 + Requires: python3-pyusb +-Requires: python3-pyOpenSSL + Requires: python3-qrcode-core >= 5.0.0 + Requires: python3-requests + Requires: python3-six +diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py +index cec3d93..88c6b62 100644 +--- a/ipaserver/plugins/cert.py ++++ b/ipaserver/plugins/cert.py +@@ -30,7 +30,6 @@ import cryptography.x509 + from cryptography.hazmat.primitives import hashes, serialization + from dns import resolver, reversename + import six +-import sys + + from ipalib import Command, Str, Int, Flag, StrEnum + from ipalib import api +@@ -1623,19 +1622,7 @@ class cert_find(Search, CertMethod): + ) + + def _get_cert_key(self, cert): +- # for cert-find with a certificate value +- if isinstance(cert, x509.IPACertificate): +- return (DN(cert.issuer), cert.serial_number) +- +- issuer = [] +- for oid, value in cert.get_issuer().get_components(): +- issuer.append( +- '{}={}'.format(oid.decode('utf-8'), value.decode('utf-8')) +- ) +- issuer = ','.join(issuer) +- # Use this to flip from OpenSSL reverse to X500 ordering +- issuer = DN(issuer).x500_text() +- return (DN(issuer), cert.get_serial_number()) ++ return (DN(cert.issuer), cert.serial_number) + + def _cert_search(self, pkey_only, **options): + result = collections.OrderedDict() +@@ -1755,11 +1742,6 @@ class cert_find(Search, CertMethod): + return result, False, complete + + def _ldap_search(self, all, pkey_only, no_members, **options): +- # defer import of the OpenSSL module to not affect the requests +- # module which will use pyopenssl if this is available. +- if sys.modules.get('OpenSSL.SSL', False) is None: +- del sys.modules["OpenSSL.SSL"] +- import OpenSSL.crypto + ldap = self.api.Backend.ldap2 + + filters = [] +@@ -1818,14 +1800,12 @@ class cert_find(Search, CertMethod): + ca_enabled = getattr(context, 'ca_enabled') + for entry in entries: + for attr in ('usercertificate', 'usercertificate;binary'): +- for der in entry.raw.get(attr, []): +- cert = OpenSSL.crypto.load_certificate( +- OpenSSL.crypto.FILETYPE_ASN1, der) ++ for cert in entry.get(attr, []): + cert_key = self._get_cert_key(cert) + try: + obj = result[cert_key] + except KeyError: +- obj = {'serial_number': cert.get_serial_number()} ++ obj = {'serial_number': cert.serial_number} + if not pkey_only and (all or not ca_enabled): + # Retrieving certificate details is now deferred + # until after all certificates are collected. + +From 3b1dbcdba2994bf57908f530913998e9ab888e4c Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Jun 16 2023 19:09:52 +0000 +Subject: Revert "cert_find: fix call with --all" + + +This reverts commit 1f30cc65276a532e7288217f216b72a2b0628c8f. + +The problem isn't with python-cryptography, it is with the +IPACertificate class which does way more work on a certificate +than is necessary in cert-find. + +Related: https://pagure.io/freeipa/issue/9331 +Reviewed-By: Florence Blanc-Renaud + +--- + +diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py +index 88c6b62..ba37525 100644 +--- a/ipaserver/plugins/cert.py ++++ b/ipaserver/plugins/cert.py +@@ -1812,7 +1812,6 @@ class cert_find(Search, CertMethod): + # For the case of CA-less we need to keep + # the certificate because getting it again later + # would require unnecessary LDAP searches. +- cert = cert.to_cryptography() + obj['certificate'] = ( + base64.b64encode( + cert.public_bytes(x509.Encoding.DER)) + +From d00fd3398c32beb2c3e72f4878c87f9d2c0e833d Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Jun 16 2023 19:09:52 +0000 +Subject: Use the python-cryptography parser directly in cert-find + + +cert-find is a rather complex beast because it not only +looks for certificates in the optional CA but within the +IPA LDAP database as well. It has a process to deduplicate +the certificates since any PKI issued certificates will +also be associated with an IPA record. + +In order to obtain the data to deduplicate the certificates +the cert from LDAP must be parser for issuer and serial number. +ipaldap has automation to determine the datatype of an +attribute and will use the ipalib.x509 IPACertificate class to +decode a certificate automatically if you access +entry['usercertificate']. + +The downside is that this is comparatively slow. Here is the +parse time in microseconds: + +cryptography 0.0081 +OpenSSL.crypto 0.2271 +ipalib.x509 2.6814 + +Since only issuer and subject are required there is no need to +make the expensive IPACertificate call. + +The IPACertificate parsing time is fine if you're parsing one +certificate but if the LDAP search returns a lot of certificates, +say in the thousands, then those microseconds add up quickly. +In testing it took ~17 seconds to parse 5k certificates (excluding +transmission overhead, etc). + +cert-find when there are a lot of certificates has been +historically slow. It isn't related to the CA which returns +large sets (well, 5k anyway) in a second or two. It was the +LDAP comparision adding tens of seconds to the runtime. + +When searching with the default sizelimit of 100 the time is +~10s without this patch. With it the time is 1.5s. + +CLI times from before and after searching for all certs: + +original: + +------------------------------- +Number of entries returned 5038 +------------------------------- +real 0m15.507s +user 0m0.828s +sys 0m0.241s + +using cryptography: + +real 0m4.037s +user 0m0.816s +sys 0m0.193s + +Fixes: https://pagure.io/freeipa/issue/9331 + +Signed-off-by: Rob Crittenden +Reviewed-By: Florence Blanc-Renaud + +--- + +diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py +index ba37525..619be83 100644 +--- a/ipaserver/plugins/cert.py ++++ b/ipaserver/plugins/cert.py +@@ -1800,7 +1800,8 @@ class cert_find(Search, CertMethod): + ca_enabled = getattr(context, 'ca_enabled') + for entry in entries: + for attr in ('usercertificate', 'usercertificate;binary'): +- for cert in entry.get(attr, []): ++ for der in entry.raw.get(attr, []): ++ cert = cryptography.x509.load_der_x509_certificate(der) + cert_key = self._get_cert_key(cert) + try: + obj = result[cert_key] +diff --git a/ipatests/test_xmlrpc/test_cert_plugin.py b/ipatests/test_xmlrpc/test_cert_plugin.py +index 433cebc..583c67f 100644 +--- a/ipatests/test_xmlrpc/test_cert_plugin.py ++++ b/ipatests/test_xmlrpc/test_cert_plugin.py +@@ -254,6 +254,16 @@ class test_cert(BaseCert): + result = _emails_are_valid(email_addrs, []) + assert not result + ++ def test_00012_cert_find_all(self): ++ """ ++ Test that cert-find --all returns successfully. ++ ++ We don't know how many we'll get but there should be at least 10 ++ by default. ++ """ ++ res = api.Command['cert_find'](all=True) ++ assert 'count' in res and res['count'] >= 10 ++ + def test_99999_cleanup(self): + """ + Clean up cert test data +@@ -283,7 +293,7 @@ class test_cert_find(XMLRPC_test): + + short = api.env.host.split('.', maxsplit=1)[0] + +- def test_0001_find_all(self): ++ def test_0001_find_all_certs(self): + """ + Search for all certificates. + + diff --git a/SOURCES/0002-trust-add-handle-missing-msSFU30MaxGidNumber_rhbz#2162355.patch b/SOURCES/0002-trust-add-handle-missing-msSFU30MaxGidNumber_rhbz#2162355.patch deleted file mode 100644 index 965e3bd..0000000 --- a/SOURCES/0002-trust-add-handle-missing-msSFU30MaxGidNumber_rhbz#2162355.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 703ab8c4dfb7f8fd1540c3849ad469d39695a26f Mon Sep 17 00:00:00 2001 -From: Florence Blanc-Renaud -Date: Jan 25 2023 16:57:02 +0000 -Subject: trust-add: handle missing msSFU30MaxGidNumber - - -When ipa trust-add is executed with --range-type ad-trust-posix, -the server tries to find the max uidnumber and max gidnumber -from AD domain controller. -The values are extracted from the entry -CN=,CN=ypservers,CN=ypServ30,CN=RpcServices,CN=System, -in the msSFU30MaxUidNumber and msSFU30MaxGidNumber attributes. - -msSFU30MaxUidNumber is required but not msSFU30MaxGidNumber. -In case msSFU30MaxGidNumber is missing, the code is currently assigning -a "None" value and later on evaluates the max between this value and -msSFU30MaxUidNumber. The max function cannot compare None and a list -of string and triggers an exception. - -To avoid the exception, assign [b'0'] to max gid if msSFU30MaxGidNumber -is missing. This way, the comparison succeeds and max returns the -value from msSFU30MaxUidNumber. - -Fixes: https://pagure.io/freeipa/issue/9310 -Signed-off-by: Florence Blanc-Renaud -Reviewed-By: Rob Crittenden - ---- - -diff --git a/ipaserver/plugins/trust.py b/ipaserver/plugins/trust.py -index c074f6d..79264b8 100644 ---- a/ipaserver/plugins/trust.py -+++ b/ipaserver/plugins/trust.py -@@ -379,7 +379,10 @@ def add_range(myapi, trustinstance, range_name, dom_sid, *keys, **options): - range_type = u'ipa-ad-trust-posix' - - max_uid = info.get('msSFU30MaxUidNumber') -- max_gid = info.get('msSFU30MaxGidNumber', None) -+ # if max_gid is missing, assume 0 and the max will -+ # be obtained from max_uid. We just checked that -+ # msSFU30MaxUidNumber is defined -+ max_gid = info.get('msSFU30MaxGidNumber', [b'0']) - max_id = int(max(max_uid, max_gid)[0]) - - base_id = int(info.get('msSFU30OrderNumber')[0]) - diff --git a/SOURCES/0003-Backport-latest-test-fixes-python3-ipatests_rhbz#2166929.patch b/SOURCES/0003-Backport-latest-test-fixes-python3-ipatests_rhbz#2166929.patch deleted file mode 100644 index b980ab8..0000000 --- a/SOURCES/0003-Backport-latest-test-fixes-python3-ipatests_rhbz#2166929.patch +++ /dev/null @@ -1,76 +0,0 @@ -From e8ef2c2f226704ce510525f07675107179124a95 Mon Sep 17 00:00:00 2001 -From: Sumedh Sidhaye -Date: Feb 02 2023 06:53:56 +0000 -Subject: With the commit #99a74d7, 389-ds changed the message returned in ipa-healthcheck. - - -Previously the message was: - -"\n\nIn Directory Server, we offer one hash suitable for this " -"(PBKDF2_SHA256) and one hash\nfor \"legacy\" support (SSHA512)." -"\n\nYour configuration does not use these for password storage " -"or the root password storage\nscheme.\n" - -but now the message is: - -\n\nIn Directory Server, we offer one hash suitable for this " -"(PBKDF2-SHA512) and one hash\nfor \"legacy\" support (SSHA512)." -"\n\nYour configuration does not use these for password storage " -"or the root password storage\nscheme.\n" - -PBKDF2_SHA256 has been replaced with PBKDF2-SHA512 - -Pagure: https://pagure.io/freeipa/issue/9238 - -Signed-off-by: Sumedh Sidhaye -Reviewed-By: Florence Blanc-Renaud -Reviewed-By: Alexander Bokovoy -Reviewed-By: Stanislav Levin -Reviewed-By: Florence Blanc-Renaud -Reviewed-By: Alexander Bokovoy -Reviewed-By: Stanislav Levin - ---- - -diff --git a/ipatests/test_integration/test_ipahealthcheck.py b/ipatests/test_integration/test_ipahealthcheck.py -index 18a665e..60e8de9 100644 ---- a/ipatests/test_integration/test_ipahealthcheck.py -+++ b/ipatests/test_integration/test_ipahealthcheck.py -@@ -1312,9 +1312,6 @@ class TestIpaHealthCheck(IntegrationTest): - """ - error_msg = ( - "\n\nIn Directory Server, we offer one hash suitable for this " -- "(PBKDF2_SHA256) and one hash\nfor \"legacy\" support (SSHA512)." -- "\n\nYour configuration does not use these for password storage " -- "or the root password storage\nscheme.\n" - ) - returncode, data = run_healthcheck( - self.master, "ipahealthcheck.ds.config", "ConfigCheck", - -From 1bdd8147e7fa1032025dc6f6868e26f285744ee1 Mon Sep 17 00:00:00 2001 -From: Florence Blanc-Renaud -Date: Jan 11 2023 11:56:30 +0000 -Subject: ipatests: mark test_smb as xfail - - -Mark the test test_smb.py::TestSMB::test_smb_service_s4u2self as xfail. - -Related: https://pagure.io/freeipa/issue/9124 -Signed-off-by: Florence Blanc-Renaud -Reviewed-By: Alexander Bokovoy - ---- - -diff --git a/ipatests/test_integration/test_smb.py b/ipatests/test_integration/test_smb.py -index eb3981b..30f8d59 100644 ---- a/ipatests/test_integration/test_smb.py -+++ b/ipatests/test_integration/test_smb.py -@@ -349,6 +349,7 @@ class TestSMB(IntegrationTest): - @pytest.mark.skipif( - osinfo.id == 'fedora' and osinfo.version_number <= (31,), - reason='Test requires krb 1.18') -+ @pytest.mark.xfail(reason="Pagure ticket 9124", strict=True) - def test_smb_service_s4u2self(self): - """Test S4U2Self operation by IPA service - against both AD and IPA users - diff --git a/SOURCES/0003-Upgrade-add-PKI-drop-in-file-if-missing_rhbz#2215336.patch b/SOURCES/0003-Upgrade-add-PKI-drop-in-file-if-missing_rhbz#2215336.patch new file mode 100644 index 0000000..b719fa3 --- /dev/null +++ b/SOURCES/0003-Upgrade-add-PKI-drop-in-file-if-missing_rhbz#2215336.patch @@ -0,0 +1,87 @@ +From 86c1426b2d376a390e87b074d3e10d85fa124abf Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Jun 21 2023 17:02:48 +0000 +Subject: Upgrade: add PKI drop-in file if missing + + +During the installation of IPA server, the installer adds a drop-in +file in /etc/systemd/system/pki-tomcatd@pki-tomcat.service.d/ipa.conf +that ensures the CA is reachable before the start command returns. +If the file is missing (for instance because the server was installed +with an old version before this drop-in was created), the upgrade +should add the file. + +Fixes: https://pagure.io/freeipa/issue/9381 + +Signed-off-by: Florence Blanc-Renaud +Reviewed-By: Rob Crittenden + +--- + +diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py +index dd22ac2..e4dc7ae 100644 +--- a/ipaserver/install/server/upgrade.py ++++ b/ipaserver/install/server/upgrade.py +@@ -1737,6 +1737,10 @@ def upgrade_configuration(): + os.path.join(paths.USR_SHARE_IPA_DIR, + "ipa-kdc-proxy.conf.template")) + if ca.is_configured(): ++ # Ensure that the drop-in file is present ++ if not os.path.isfile(paths.SYSTEMD_PKI_TOMCAT_IPA_CONF): ++ ca.add_ipa_wait() ++ + # Handle upgrade of AJP connector configuration + rewrite = ca.secure_ajp_connector() + if ca.ajp_secret: + +From 356ec5cbfe0876686239f938bdf54892dc30571e Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Jun 21 2023 17:02:48 +0000 +Subject: Integration test: add a test for upgrade and PKI drop-in file + + +Add an upgrade test with the following scenario: +- remove PKI drop-in file (to simulate an upgrade from an old +version) +- remove caECServerCertWithSCT profile from LDAP +- launch the ipa-server-upgrade command +- check that the upgrade added the file + +Related: https://pagure.io/freeipa/issue/9381 + +Signed-off-by: Florence Blanc-Renaud +Reviewed-By: Rob Crittenden + +--- + +diff --git a/ipatests/test_integration/test_upgrade.py b/ipatests/test_integration/test_upgrade.py +index 9203503..182e3b5 100644 +--- a/ipatests/test_integration/test_upgrade.py ++++ b/ipatests/test_integration/test_upgrade.py +@@ -455,3 +455,25 @@ class TestUpgrade(IntegrationTest): + assert 'tXTRecord' in location_krb_rec + assert len(location_krb_rec['tXTRecord']) == 1 + assert location_krb_rec['tXTRecord'][0] == f'"{realm}"' ++ ++ def test_pki_dropin_file(self): ++ """Test that upgrade adds the drop-in file if missing ++ ++ Test for ticket 9381 ++ Simulate an update from a version that didn't provide ++ /etc/systemd/system/pki-tomcatd@pki-tomcat.service.d/ipa.conf, ++ remove one of the certificate profiles from LDAP and check that upgrade ++ completes successfully and adds the missing file. ++ When the drop-in file is missing, the upgrade tries to login to ++ PKI in order to migrate the profile and fails because PKI failed to ++ start. ++ """ ++ self.master.run_command(["rm", "-f", paths.SYSTEMD_PKI_TOMCAT_IPA_CONF]) ++ ldif = textwrap.dedent(""" ++ dn: cn=caECServerCertWithSCT,ou=certificateProfiles,ou=ca,o=ipaca ++ changetype: delete ++ """) ++ tasks.ldapmodify_dm(self.master, ldif) ++ self.master.run_command(['ipa-server-upgrade']) ++ assert self.master.transport.file_exists( ++ paths.SYSTEMD_PKI_TOMCAT_IPA_CONF) + diff --git a/SOURCES/0004-Upgrade-fix-replica-agreement_rhbz#2216551.patch b/SOURCES/0004-Upgrade-fix-replica-agreement_rhbz#2216551.patch new file mode 100644 index 0000000..4d795e4 --- /dev/null +++ b/SOURCES/0004-Upgrade-fix-replica-agreement_rhbz#2216551.patch @@ -0,0 +1,233 @@ +From d29b47512a39ada02fb371521994576cd9815a6c Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Mon, 19 Jun 2023 10:36:29 +0200 +Subject: [PATCH] Upgrade: fix replica agreement + +The upgrade checks the replication agreements to ensure that +some attributes are excluded from replication. The agreements +are stored in entries like +cn=serverToreplica,cn=replica,cn=_suffix_,cn=mapping tree,cn=config +but those entries are managed by the replication topology plugin +and should not be updated directly. The consequence is that the update +of the attributes fails and ipa-server-update prints an error message: + +Error caught updating nsDS5ReplicatedAttributeList: Server is unwilling +to perform: Entry and attributes are managed by topology plugin.No direct +modifications allowed. +Error caught updating nsDS5ReplicatedAttributeListTotal: Server is +unwilling to perform: Entry and attributes are managed by topology +plugin.No direct modifications allowed. + +The upgrade continues but the replication is not excluding +passwordgraceusertime. + +Instead of editing the agreements, perform the modifications on +the topology segments. + +Fixes: https://pagure.io/freeipa/issue/9385 +Signed-off-by: Florence Blanc-Renaud +Reviewed-By: Rob Crittenden +--- + .../install/plugins/fix_replica_agreements.py | 80 +++++++++---------- + 1 file changed, 38 insertions(+), 42 deletions(-) + +diff --git a/ipaserver/install/plugins/fix_replica_agreements.py b/ipaserver/install/plugins/fix_replica_agreements.py +index c0cdd3eb1..d963753d0 100644 +--- a/ipaserver/install/plugins/fix_replica_agreements.py ++++ b/ipaserver/install/plugins/fix_replica_agreements.py +@@ -22,6 +22,7 @@ import logging + from ipaserver.install import replication + from ipalib import Registry + from ipalib import Updater ++from ipalib import errors + + logger = logging.getLogger(__name__) + +@@ -41,35 +42,42 @@ class update_replica_attribute_lists(Updater): + def execute(self, **options): + # We need an LDAPClient connection to the backend + logger.debug("Start replication agreement exclude list update task") +- conn = self.api.Backend.ldap2 + +- repl = replication.ReplicationManager(self.api.env.realm, +- self.api.env.host, +- None, conn=conn) +- +- # We need to update only IPA replica agreements, not winsync +- ipa_replicas = repl.find_ipa_replication_agreements() +- +- logger.debug("Found %d agreement(s)", len(ipa_replicas)) +- +- for replica in ipa_replicas: +- for desc in replica.get('description', []): +- logger.debug('%s', desc) +- +- self._update_attr(repl, replica, +- 'nsDS5ReplicatedAttributeList', +- replication.EXCLUDES, template=EXCLUDE_TEMPLATE) +- self._update_attr(repl, replica, +- 'nsDS5ReplicatedAttributeListTotal', +- replication.TOTAL_EXCLUDES, template=EXCLUDE_TEMPLATE) +- self._update_attr(repl, replica, +- 'nsds5ReplicaStripAttrs', replication.STRIP_ATTRS) ++ # Find suffixes ++ suffixes = self.api.Command.topologysuffix_find()['result'] ++ for suffix in suffixes: ++ suffix_name = suffix['cn'][0] ++ # Find segments ++ sgmts = self.api.Command.topologysegment_find( ++ suffix_name, all=True)['result'] ++ for segment in sgmts: ++ updates = {} ++ updates = self._update_attr( ++ segment, updates, ++ 'nsds5replicatedattributelist', ++ replication.EXCLUDES, template=EXCLUDE_TEMPLATE) ++ updates = self._update_attr( ++ segment, updates, ++ 'nsds5replicatedattributelisttotal', ++ replication.TOTAL_EXCLUDES, template=EXCLUDE_TEMPLATE) ++ updates = self._update_attr( ++ segment, updates, ++ 'nsds5replicastripattrs', replication.STRIP_ATTRS) ++ if updates: ++ try: ++ self.api.Command.topologysegment_mod( ++ suffix_name, segment['cn'][0], ++ **updates) ++ except errors.EmptyModlist: ++ # No update done ++ logger.debug("No update required for the segment %s", ++ segment['cn'][0]) + + logger.debug("Done updating agreements") + + return False, [] # No restart, no updates + +- def _update_attr(self, repl, replica, attribute, values, template='%s'): ++ def _update_attr(self, segment, updates, attribute, values, template='%s'): + """Add or update an attribute of a replication agreement + + If the attribute doesn't already exist, it is added and set to +@@ -77,27 +85,21 @@ class update_replica_attribute_lists(Updater): + If the attribute does exist, `values` missing from it are just + appended to the end, also space-separated. + +- :param repl: Replication manager +- :param replica: Replica agreement ++ :param: updates: dict containing the updates ++ :param segment: dict containing segment information + :param attribute: Attribute to add or update + :param values: List of values the attribute should hold + :param template: Template to use when adding attribute + """ +- attrlist = replica.single_value.get(attribute) ++ attrlist = segment.get(attribute) + if attrlist is None: + logger.debug("Adding %s", attribute) + + # Need to add it altogether +- replica[attribute] = [template % " ".join(values)] +- +- try: +- repl.conn.update_entry(replica) +- logger.debug("Updated") +- except Exception as e: +- logger.error("Error caught updating replica: %s", str(e)) ++ updates[attribute] = template % " ".join(values) + + else: +- attrlist_normalized = attrlist.lower().split() ++ attrlist_normalized = attrlist[0].lower().split() + missing = [a for a in values + if a.lower() not in attrlist_normalized] + +@@ -105,14 +107,8 @@ class update_replica_attribute_lists(Updater): + logger.debug("%s needs updating (missing: %s)", attribute, + ', '.join(missing)) + +- replica[attribute] = [ +- '%s %s' % (attrlist, ' '.join(missing))] ++ updates[attribute] = '%s %s' % (attrlist[0], ' '.join(missing)) + +- try: +- repl.conn.update_entry(replica) +- logger.debug("Updated %s", attribute) +- except Exception as e: +- logger.error("Error caught updating %s: %s", +- attribute, str(e)) + else: + logger.debug("%s: No update necessary", attribute) ++ return updates +-- +2.41.0 + +From 93d97b59600c15e5028ee39b0e98450544165158 Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Mon, 19 Jun 2023 10:36:59 +0200 +Subject: [PATCH] Integration tests: add a test to ipa-server-upgrade + +Add an integration test ensuring that the upgrade +properly updates the attributes to be excluded from +replication. + +Related: https://pagure.io/freeipa/issue/9385 +Signed-off-by: Florence Blanc-Renaud +Reviewed-By: Rob Crittenden +--- + .../test_simple_replication.py | 30 +++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/ipatests/test_integration/test_simple_replication.py b/ipatests/test_integration/test_simple_replication.py +index 17092a499..d1e65ef7c 100644 +--- a/ipatests/test_integration/test_simple_replication.py ++++ b/ipatests/test_integration/test_simple_replication.py +@@ -23,8 +23,10 @@ import pytest + + from ipaplatform.paths import paths + from ipapython.dn import DN ++from ipaserver.install.replication import EXCLUDES + from ipatests.pytest_ipa.integration import tasks + from ipatests.test_integration.base import IntegrationTest ++from ipatests.test_integration.test_topology import find_segment + + + def check_replication(source_host, dest_host, login): +@@ -104,6 +106,34 @@ class TestSimpleReplication(IntegrationTest): + [paths.IPA_CUSTODIA_CHECK, self.master.hostname] + ) + ++ def test_fix_agreements(self): ++ """Test that upgrade fixes the list of attributes excluded from repl ++ ++ Test for ticket 9385 ++ """ ++ # Prepare the server by removing some values from ++ # from the nsDS5ReplicatedAttributeList ++ segment = find_segment(self.master, self.replicas[0], "domain") ++ self.master.run_command([ ++ "ipa", "topologysegment-mod", "domain", segment, ++ "--replattrs", ++ "(objectclass=*) $ EXCLUDE memberof idnssoaserial entryusn"]) ++ # Run the upgrade ++ result = self.master.run_command(["ipa-server-upgrade"]) ++ # Ensure that the upgrade updated the attribute without error ++ errmsg = "Error caught updating nsDS5ReplicatedAttributeList" ++ assert errmsg not in result.stdout_text ++ # Check the updated value ++ suffix = DN(self.master.domain.basedn) ++ dn = DN(('cn', str(suffix)), ('cn', 'mapping tree'), ('cn', 'config')) ++ result = tasks.ldapsearch_dm(self.master, str(dn), ++ ["nsDS5ReplicatedAttributeList"]) ++ output = result.stdout_text.lower() ++ ++ template = 'nsDS5ReplicatedAttributeList: (objectclass=*) $ EXCLUDE %s' ++ expected_value = template % " ".join(EXCLUDES) ++ assert expected_value.lower() in output ++ + def test_replica_removal(self): + """Test replica removal""" + result = self.master.run_command(['ipa-replica-manage', 'list']) +-- +2.41.0 + diff --git a/SOURCES/0004-server-install-remove-error-log-about-missing-bkup-file_rhbz#2160389.patch b/SOURCES/0004-server-install-remove-error-log-about-missing-bkup-file_rhbz#2160389.patch deleted file mode 100644 index 63a358c..0000000 --- a/SOURCES/0004-server-install-remove-error-log-about-missing-bkup-file_rhbz#2160389.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 6f50b00953c0000d6da8db0f5e8974ae33d7b5d5 Mon Sep 17 00:00:00 2001 -From: Florence Blanc-Renaud -Date: Jan 16 2023 07:44:50 +0000 -Subject: server install: remove error log about missing bkup file - - -The client installer code can be called in 3 different ways: -- from ipa-client-install CLI -- from ipa-replica-install CLI if the client is not already installed -- from ipa-server-install - -In the last case, the client installer is called with -options.on_master=True -As a result, it's skipping the part that is creating the krb5 -configuration: - if not options.on_master: - nolog = tuple() - configure_krb5_conf(...) - -The configure_krb5_conf method is the place where the krb5.conf file is -backup'ed with the extention ".ipabkp". For a master installation, this -code is not called and the ipabkp file does not exist => delete raises -an error. - -When delete fails because the file does not exist, no need to log an -error message. - -Fixes: https://pagure.io/freeipa/issue/9306 -Signed-off-by: Florence Blanc-Renaud -Reviewed-By: Rob Crittenden - ---- - -diff --git a/ipaclient/install/client.py b/ipaclient/install/client.py -index e5d3e82..6e7f17d 100644 ---- a/ipaclient/install/client.py -+++ b/ipaclient/install/client.py -@@ -124,10 +124,9 @@ def cleanup(func): - os.rmdir(ccache_dir) - except OSError: - pass -- try: -- os.remove(krb_name + ".ipabkp") -- except OSError: -- logger.error("Could not remove %s.ipabkp", krb_name) -+ # During master installation, the .ipabkp file is not created -+ # Ignore the delete error if it is "file does not exist" -+ remove_file(krb_name + ".ipabkp") - - return inner - - diff --git a/SOURCES/0005-OTP-fix-data-type-to-avoid-endianness-issue_rhbz#2218293.patch b/SOURCES/0005-OTP-fix-data-type-to-avoid-endianness-issue_rhbz#2218293.patch new file mode 100644 index 0000000..6d5b7b6 --- /dev/null +++ b/SOURCES/0005-OTP-fix-data-type-to-avoid-endianness-issue_rhbz#2218293.patch @@ -0,0 +1,52 @@ +From a7e167154b889f75463ccc9cd91a75c1afb22da9 Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Jun 28 2023 19:43:16 +0000 +Subject: OTP: fix data type to avoid endianness issue + + +When 389-ds process an OTP authentication, the ipa-pwd-extop +plugin reads a buffer to extract the authentication type. +The type is stored in an int but the data is a ber_tag_t. + +On big endian machines the type cast does not cause any issue +but on s390x the buffer that should return 128 is seen as 0. + +As a consequence, the plugin considers that the method is not +LDAP_AUTH_SIMPLE and exits early, without processing the OTP. + +The fix is simple and consists in using the right type +(ber_tag_t is an unsigned long). + +Fixes: https://pagure.io/freeipa/issue/9402 + +Signed-off-by: Florence Blanc-Renaud +Reviewed-By: Rob Crittenden + +--- + +diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c +index 9375941..4562652 100644 +--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c ++++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/prepost.c +@@ -1433,7 +1433,7 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb) + Slapi_DN *target_sdn = NULL; + Slapi_DN *sdn = NULL; + const char *dn = NULL; +- int method = 0; ++ ber_tag_t method = 0; + bool syncreq; + bool otpreq; + int ret = 0; +@@ -1454,8 +1454,10 @@ static int ipapwd_pre_bind(Slapi_PBlock *pb) + } + + /* We're only interested in simple authentication. */ +- if (method != LDAP_AUTH_SIMPLE || credentials->bv_len == 0) ++ if (method != LDAP_AUTH_SIMPLE || credentials->bv_len == 0) { ++ LOG("Not handled (not simple bind or NULL dn/credentials)\n"); + return 0; ++ } + + /* Retrieve the user's entry. */ + sdn = slapi_sdn_dup(target_sdn); + diff --git a/SOURCES/0005-automember-rebuild-add-a-notice-about-high-CPU-usage_rhbz#2018198.patch b/SOURCES/0005-automember-rebuild-add-a-notice-about-high-CPU-usage_rhbz#2018198.patch deleted file mode 100644 index 4fc3a5d..0000000 --- a/SOURCES/0005-automember-rebuild-add-a-notice-about-high-CPU-usage_rhbz#2018198.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 2deaaa788cbdde22d5b15566599fdcf7a10f02c6 Mon Sep 17 00:00:00 2001 -From: Florence Blanc-Renaud -Date: Feb 02 2023 10:08:26 +0000 -Subject: automember-rebuild: add a notice about high CPU usage - - -The automember-rebuild task may require high CPU usage -if many users/hosts/groups are processed. -Add a note in the ipa automember-rebuild CLI output -and in the WebUI confirmation message. - -Fixes: https://pagure.io/freeipa/issue/9320 -Signed-off-by: Florence Blanc-Renaud -Reviewed-By: Francisco Trivino - ---- - -diff --git a/install/ui/test/data/i18n_messages.json b/install/ui/test/data/i18n_messages.json -index 49d2883..5b73548 100644 ---- a/install/ui/test/data/i18n_messages.json -+++ b/install/ui/test/data/i18n_messages.json -@@ -7,7 +7,7 @@ - "actions": { - "apply": "Apply", - "automember_rebuild": "Rebuild auto membership", -- "automember_rebuild_confirm": "Are you sure you want to rebuild auto membership?", -+ "automember_rebuild_confirm": "Are you sure you want to rebuild auto membership? In case of a high number of users, hosts or groups, the operation may require high CPU usage.", - "automember_rebuild_success": "Automember rebuild membership task completed", - "confirm": "Are you sure you want to proceed with the action?", - "delete_confirm": "Are you sure you want to delete ${object}?", -diff --git a/ipaclient/plugins/automember.py b/ipaclient/plugins/automember.py -index df4a2e5..7108dc9 100644 ---- a/ipaclient/plugins/automember.py -+++ b/ipaclient/plugins/automember.py -@@ -34,3 +34,11 @@ class automember_add_condition(MethodOverride): - flags=['suppress_empty'], - ), - ) -+ -+ -+@register(override=True, no_fail=True) -+class automember_rebuild(MethodOverride): -+ def interactive_prompt_callback(self, kw): -+ msg = _('IMPORTANT: In case of a high number of users, hosts or ' -+ 'groups, the operation may require high CPU usage.') -+ self.Backend.textui.print_plain(msg) -diff --git a/ipaserver/plugins/internal.py b/ipaserver/plugins/internal.py -index 5ffa7a2..e1e920f 100644 ---- a/ipaserver/plugins/internal.py -+++ b/ipaserver/plugins/internal.py -@@ -160,7 +160,11 @@ class i18n_messages(Command): - "actions": { - "apply": _("Apply"), - "automember_rebuild": _("Rebuild auto membership"), -- "automember_rebuild_confirm": _("Are you sure you want to rebuild auto membership?"), -+ "automember_rebuild_confirm": _( -+ "Are you sure you want to rebuild auto membership? In case of " -+ "a high number of users, hosts or groups, the operation " -+ "may require high CPU usage." -+ ), - "automember_rebuild_success": _("Automember rebuild membership task completed"), - "confirm": _("Are you sure you want to proceed with the action?"), - "delete_confirm": _("Are you sure you want to delete ${object}?"), - diff --git a/SOURCES/0006-Backport-test-updates-8-9-release_rhbz#2218847.patch b/SOURCES/0006-Backport-test-updates-8-9-release_rhbz#2218847.patch new file mode 100644 index 0000000..8b44931 --- /dev/null +++ b/SOURCES/0006-Backport-test-updates-8-9-release_rhbz#2218847.patch @@ -0,0 +1,173 @@ +From 7a94acca6a9efb546f1cf59f63fcb89f98944ea5 Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Thu, 25 May 2023 08:16:33 +0200 +Subject: [PATCH] ACME tests: fix issue_and_expire_acme_cert method + +The fixture issue_and_expire_acme_cert is changing the date +on master and client. It also resets the admin password as +it gets expired after the date change. +Currently the code is resetting the password by performing +kinit on the client, which leaves the master with an expired +ticket in its cache. Reset the password on the master instead +in order to have a valid ticket for the next operations. + +Fixes: https://pagure.io/freeipa/issue/9383 + +Signed-off-by: Florence Blanc-Renaud +Reviewed-By: Mohammad Rizwan +--- + ipatests/test_integration/test_acme.py | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/ipatests/test_integration/test_acme.py b/ipatests/test_integration/test_acme.py +index c73f441fc..c69e810da 100644 +--- a/ipatests/test_integration/test_acme.py ++++ b/ipatests/test_integration/test_acme.py +@@ -583,20 +583,20 @@ class TestACMERenew(IntegrationTest): + tasks.kdestroy_all(host) + tasks.move_date(host, 'stop', '+90days') + +- tasks.get_kdcinfo(host) ++ tasks.get_kdcinfo(self.master) + # Note raiseonerr=False: + # the assert is located after kdcinfo retrieval. + # run kinit command repeatedly until sssd gets settle + # after date change + tasks.run_repeatedly( +- host, "KRB5_TRACE=/dev/stdout kinit admin", ++ self.master, "KRB5_TRACE=/dev/stdout kinit admin", + stdin_text='{0}\n{0}\n{0}\n'.format( +- self.clients[0].config.admin_password ++ self.master.config.admin_password + ) + ) + # Retrieve kdc.$REALM after the password change, just in case SSSD + # domain status flipped to online during the password change. +- tasks.get_kdcinfo(host) ++ tasks.get_kdcinfo(self.master) + + yield + +-- +2.41.0 + +From 998bafee86a870ad1ea4d6bccf12f0fae64c398c Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Wed, 31 May 2023 11:50:14 +0200 +Subject: [PATCH] ipatest: remove xfail from test_smb + +test_smb is now successful because the windows server version +has been updated to windows-server-2022 with +- KB5012170 +- KB5025230 +- KB5022507 +- servicing stack 10.0.20348.1663 +in freeipa-pr-ci commit 3ba4151. + +Remove the xfail. + +Fixes: https://pagure.io/freeipa/issue/9124 +Signed-off-by: Florence Blanc-Renaud +Reviewed-By: Mohammad Rizwan +--- + ipatests/test_integration/test_smb.py | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/ipatests/test_integration/test_smb.py b/ipatests/test_integration/test_smb.py +index 30f8d5901..eb3981bdd 100644 +--- a/ipatests/test_integration/test_smb.py ++++ b/ipatests/test_integration/test_smb.py +@@ -349,7 +349,6 @@ class TestSMB(IntegrationTest): + @pytest.mark.skipif( + osinfo.id == 'fedora' and osinfo.version_number <= (31,), + reason='Test requires krb 1.18') +- @pytest.mark.xfail(reason="Pagure ticket 9124", strict=True) + def test_smb_service_s4u2self(self): + """Test S4U2Self operation by IPA service + against both AD and IPA users +-- +2.41.0 + +From 1b51fa4cb07380d1102891233e85a7940f804c72 Mon Sep 17 00:00:00 2001 +From: Anuja More +Date: Thu, 11 May 2023 12:50:10 +0530 +Subject: [PATCH] ipatests: Check that SSSD_PUBCONF_KRB5_INCLUDE_D_DIR is not + included in krb5.conf + +SSSD already provides a config snippet which includes +SSSD_PUBCONF_KRB5_INCLUDE_D_DIR, and having both breaks Java. +Test checks that krb5.conf does not include +SSSD_PUBCONF_KRB5_INCLUDE_D_DIR. + +Related: https://pagure.io/freeipa/issue/9267 + +Signed-off-by: Anuja More +Reviewed-By: Florence Blanc-Renaud +--- + .../test_integration/test_installation_client.py | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/ipatests/test_integration/test_installation_client.py b/ipatests/test_integration/test_installation_client.py +index 014b0f6ab..56e1593bf 100644 +--- a/ipatests/test_integration/test_installation_client.py ++++ b/ipatests/test_integration/test_installation_client.py +@@ -76,6 +76,21 @@ class TestInstallClient(IntegrationTest): + result = self.clients[0].run_command(['cat', '/etc/ssh/ssh_config']) + assert 'HostKeyAlgorithms' not in result.stdout_text + ++ def test_client_install_with_krb5(self): ++ """Test that SSSD_PUBCONF_KRB5_INCLUDE_D_DIR is not added in krb5.conf ++ ++ SSSD already provides a config snippet which includes ++ SSSD_PUBCONF_KRB5_INCLUDE_D_DIR, and having both breaks Java. ++ Test checks that krb5.conf does not include ++ SSSD_PUBCONF_KRB5_INCLUDE_D_DIR. ++ ++ related: https://pagure.io/freeipa/issue/9267 ++ """ ++ krb5_cfg = self.master.get_file_contents(paths.KRB5_CONF) ++ assert 'includedir {dir}'.format( ++ dir=paths.SSSD_PUBCONF_KRB5_INCLUDE_D_DIR ++ ).encode() not in krb5_cfg ++ + + class TestClientInstallBind(IntegrationTest): + """ +-- +2.41.0 + +From f599e2d67bad5945e4dcf99fdd584f01f1e20d1e Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Tue, 6 Jun 2023 09:04:48 +0200 +Subject: [PATCH] webuitests: close notification which hides Add button + +The webui test test_service.py::test_service::test_arbitrary_certificates +randomly fails. +The test is creating a new service then navigates to the Service page +and clicks on the Add Certificate button. +The notification area may still be present and hide the button, with +the message "Service successfully added". +Close all notifications before navigating to the Service page. + +Fixes: https://pagure.io/freeipa/issue/9389 +Signed-off-by: Florence Blanc-Renaud +Reviewed-By: Michal Polovka +--- + ipatests/test_webui/test_service.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/ipatests/test_webui/test_service.py b/ipatests/test_webui/test_service.py +index f1d9a9d62..e2976d73a 100644 +--- a/ipatests/test_webui/test_service.py ++++ b/ipatests/test_webui/test_service.py +@@ -296,6 +296,7 @@ class test_service(sevice_tasks): + cert_widget_sel = "div.certificate-widget" + + self.add_record(ENTITY, data) ++ self.close_notifications() + self.navigate_to_record(pkey) + + # check whether certificate section is present +-- +2.41.0 + diff --git a/SOURCES/0006-ipa-kdb-PAC-consistency-checker-needs-to-handle-child-domains-as-well_rhbz#2166324.patch b/SOURCES/0006-ipa-kdb-PAC-consistency-checker-needs-to-handle-child-domains-as-well_rhbz#2166324.patch deleted file mode 100644 index aa29c23..0000000 --- a/SOURCES/0006-ipa-kdb-PAC-consistency-checker-needs-to-handle-child-domains-as-well_rhbz#2166324.patch +++ /dev/null @@ -1,185 +0,0 @@ -From 2a0868fccbc9f4dfc540a7d3bb5dfa22c0bdce4e Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Mon, 30 Jan 2023 14:22:30 +0200 -Subject: [PATCH 1/2] ipa-kdb: PAC consistency checker needs to handle child - domains as well - -When PAC check is performed, we might get a signing TGT instead of the -client DB entry. This means it is a principal from a trusted domain but -we don't know which one exactly because we only have a krbtgt for the -forest root. This happens in MIT Kerberos 1.20 or later where KDB's -issue_pac() callback never gets the original client principal directly. - -Look into known child domains as well and make pass the check if both -NetBIOS name and SID correspond to one of the trusted domains under this -forest root. Move check for the SID before NetBIOS name check because we -can use SID of the domain in PAC to find out the right child domain in -our trusted domains' topology list. - -Fixes: https://pagure.io/freeipa/issue/9316 - -Signed-off-by: Alexander Bokovoy ---- - daemons/ipa-kdb/ipa_kdb_mspac.c | 51 +++++++++++++++++++++------------ - 1 file changed, 32 insertions(+), 19 deletions(-) - -diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c -index a15050e2166..476d1cb558a 100644 ---- a/daemons/ipa-kdb/ipa_kdb_mspac.c -+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c -@@ -1827,11 +1827,43 @@ krb5_error_code filter_logon_info(krb5_context context, - bool result; - char *domstr = NULL; - -+ ipactx = ipadb_get_context(context); -+ if (!ipactx || !ipactx->mspac) { -+ return KRB5_KDB_DBNOTINITED; -+ } -+ - domain = get_domain_from_realm_update(context, realm); - if (!domain) { - return EINVAL; - } - -+ /* check exact sid */ -+ result = dom_sid_check(&domain->domsid, info->info->info3.base.domain_sid, true); -+ if (!result) { -+ struct ipadb_mspac *mspac_ctx = ipactx->mspac; -+ result = FALSE; -+ /* Didn't match but perhaps the original PAC was issued by a child domain's DC? */ -+ for (k = 0; k < mspac_ctx->num_trusts; k++) { -+ result = dom_sid_check(&mspac_ctx->trusts[k].domsid, -+ info->info->info3.base.domain_sid, true); -+ if (result) { -+ domain = &mspac_ctx->trusts[k]; -+ break; -+ } -+ } -+ if (!result) { -+ domstr = dom_sid_string(NULL, info->info->info3.base.domain_sid); -+ krb5_klog_syslog(LOG_ERR, "PAC Info mismatch: domain = %s, " -+ "expected domain SID = %s, " -+ "found domain SID = %s", -+ domain->domain_name, domain->domain_sid, -+ domstr ? domstr : ""); -+ talloc_free(domstr); -+ return EINVAL; -+ } -+ } -+ -+ /* At this point we may have changed the domain we look at, */ - /* check netbios/flat name */ - if (strcasecmp(info->info->info3.base.logon_domain.string, - domain->flat_name) != 0) { -@@ -1843,21 +1875,6 @@ krb5_error_code filter_logon_info(krb5_context context, - return EINVAL; - } - -- /* check exact sid */ -- result = dom_sid_check(&domain->domsid, info->info->info3.base.domain_sid, true); -- if (!result) { -- domstr = dom_sid_string(NULL, info->info->info3.base.domain_sid); -- if (!domstr) { -- return EINVAL; -- } -- krb5_klog_syslog(LOG_ERR, "PAC Info mismatch: domain = %s, " -- "expected domain SID = %s, " -- "found domain SID = %s", -- domain->domain_name, domain->domain_sid, domstr); -- talloc_free(domstr); -- return EINVAL; -- } -- - /* Check if this domain has been filtered out by the trust itself*/ - if (domain->parent != NULL) { - for(k = 0; k < domain->parent->len_sid_blocklist_incoming; k++) { -@@ -1944,10 +1961,6 @@ krb5_error_code filter_logon_info(krb5_context context, - * should include different possibilities into account - * */ - if (info->info->info3.sidcount != 0) { -- ipactx = ipadb_get_context(context); -- if (!ipactx || !ipactx->mspac) { -- return KRB5_KDB_DBNOTINITED; -- } - count = info->info->info3.sidcount; - i = 0; - j = 0; - -From 1a4f2597253c750696f6cd34613b375dc30fe456 Mon Sep 17 00:00:00 2001 -From: Anuja More -Date: Mon, 30 Jan 2023 19:27:49 +0530 -Subject: [PATCH 2/2] Add test for SSH with GSSAPI auth. - -Added test for aduser with GSSAPI authentication. - -Related : https://pagure.io/freeipa/issue/9316 - -Signed-off-by: Anuja More ---- - ipatests/test_integration/test_trust.py | 46 +++++++++++++++++++++++++ - 1 file changed, 46 insertions(+) - -diff --git a/ipatests/test_integration/test_trust.py b/ipatests/test_integration/test_trust.py -index 21c814ff1a9..a1ed906c6ae 100644 ---- a/ipatests/test_integration/test_trust.py -+++ b/ipatests/test_integration/test_trust.py -@@ -527,6 +527,35 @@ def test_subordinate_suffix(self): - .format(self.ad_domain, subordinate_suffix)) - self.ad.run_command(['powershell', '-c', cmd]) - -+ def test_ssh_aduser(self): -+ """Test ssh with GSSAPI is working with aduser -+ -+ When kerberos ticket is obtained for child domain user -+ and ssh with this ticket should be successful -+ with no password prompt. -+ -+ Related : https://pagure.io/freeipa/issue/9316 -+ """ -+ testuser = 'testuser@{0}'.format(self.ad_domain) -+ testusersub = 'subdomaintestuser@{0}'.format(self.ad_subdomain) -+ -+ def sshuser(host, user): -+ tasks.kdestroy_all(host) -+ try: -+ tasks.kinit_as_user(host, user, -+ host.config.ad_admin_password -+ ) -+ ssh_cmd = "ssh -q -K -l {user} {host} hostname" -+ valid_ssh = host.run_command( -+ ssh_cmd.format(user=user, host=host.hostname) -+ ) -+ assert host.hostname in valid_ssh.stdout_text -+ finally: -+ tasks.kdestroy_all(host) -+ -+ sshuser(self.master, testuser) -+ sshuser(self.master, testusersub) -+ - def test_remove_nonposix_trust(self): - self.remove_trust(self.ad) - tasks.unconfigure_dns_for_trust(self.master, self.ad) -@@ -784,6 +813,23 @@ def test_user_gid_uid_resolution_in_external_treedomain_trust(self): - assert re.search( - testuser_regex, result.stdout_text), result.stdout_text - -+ def test_ssh_adtreeuser(self): -+ testuser = 'treetestuser@{0}'.format(self.ad_treedomain) -+ self.master.run_command(["id", testuser]) -+ tasks.clear_sssd_cache(self.master) -+ tasks.kdestroy_all(self.master) -+ try: -+ tasks.kinit_as_user(self.master, testuser, -+ password="Secret123456" -+ ) -+ ssh_cmd = "ssh -q -K -l {user} {host} hostname" -+ valid_ssh = self.master.run_command( -+ ssh_cmd.format(user=testuser, host=self.master.hostname) -+ ) -+ assert self.master.hostname in valid_ssh.stdout_text -+ finally: -+ tasks.kdestroy_all(self.master) -+ - def test_remove_external_treedomain_trust(self): - self.remove_trust(self.tree_ad) - tasks.unconfigure_dns_for_trust(self.master, self.ad, self.tree_ad) diff --git a/SOURCES/0007-Wipe-the-ipa-ca-DNS-record-when-updating-system-records_rhbz#2158775.patch b/SOURCES/0007-Wipe-the-ipa-ca-DNS-record-when-updating-system-records_rhbz#2158775.patch deleted file mode 100644 index 87b63ed..0000000 --- a/SOURCES/0007-Wipe-the-ipa-ca-DNS-record-when-updating-system-records_rhbz#2158775.patch +++ /dev/null @@ -1,64 +0,0 @@ -From b35c75d864040b98ed3f9214d5d17d32f06d6ee1 Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Mon, 11 Jul 2022 14:20:32 -0400 -Subject: [PATCH] Wipe the ipa-ca DNS record when updating system records - -If a server with a CA has been marked as hidden and -contains the last A or AAAA address then that address -would remain in the ipa-ca entry. - -This is because update-dns-system-records did not delete -values, it just re-computed them. So if no A or AAAA -records were found then the existing value was left. - -Fixes: https://pagure.io/freeipa/issue/9195 - -Signed-off-by: Rob Crittenden ---- - ipaserver/dns_data_management.py | 12 +++++++++++- - 1 file changed, 11 insertions(+), 1 deletion(-) - -diff --git a/ipaserver/dns_data_management.py b/ipaserver/dns_data_management.py -index e2bc530ee8a..aaae5446856 100644 ---- a/ipaserver/dns_data_management.py -+++ b/ipaserver/dns_data_management.py -@@ -19,6 +19,7 @@ - from time import sleep, time - - from ipalib import errors -+from ipalib.constants import IPA_CA_RECORD - from ipalib.dns import record_name_format - from ipapython.dnsutil import DNSName - from ipaserver.install import installutils -@@ -187,7 +188,7 @@ def __add_uri_records( - - def __add_ca_records_from_hostname(self, zone_obj, hostname): - assert isinstance(hostname, DNSName) and hostname.is_absolute() -- r_name = DNSName('ipa-ca') + self.domain_abs -+ r_name = DNSName(IPA_CA_RECORD) + self.domain_abs - rrsets = None - end_time = time() + CA_RECORDS_DNS_TIMEOUT - while True: -@@ -210,6 +211,7 @@ def __add_ca_records_from_hostname(self, zone_obj, hostname): - - for rrset in rrsets: - for rd in rrset: -+ logger.debug("Adding CA IP %s for %s", rd.to_text(), hostname) - rdataset = zone_obj.get_rdataset( - r_name, rd.rdtype, create=True) - rdataset.add(rd, ttl=self.TTL) -@@ -461,6 +463,14 @@ def update_base_records(self): - ) - ) - -+ # Remove the ipa-ca record(s). They will be reconstructed in -+ # get_base_records(). -+ r_name = DNSName(IPA_CA_RECORD) + self.domain_abs -+ try: -+ self.api_instance.Command.dnsrecord_del( -+ self.domain_abs, r_name, del_all=True) -+ except errors.NotFound: -+ pass - base_zone = self.get_base_records() - for record_name, node in base_zone.items(): - set_cname_template = record_name in names_requiring_cname_templates diff --git a/SOURCES/0007-ipa-kdb-fix-error-handling-of-is_master_host_rhbz#2214638.patch b/SOURCES/0007-ipa-kdb-fix-error-handling-of-is_master_host_rhbz#2214638.patch new file mode 100644 index 0000000..39d9e7f --- /dev/null +++ b/SOURCES/0007-ipa-kdb-fix-error-handling-of-is_master_host_rhbz#2214638.patch @@ -0,0 +1,85 @@ +From b5793c854035a122ed4c66f917cc427e5024e46a Mon Sep 17 00:00:00 2001 +From: Julien Rische +Date: Aug 02 2023 11:52:30 +0000 +Subject: ipa-kdb: fix error handling of is_master_host() + + +Adding proper error handling to the is_master_host() function to allow +it to make the difference between the absence of a master host object +and a connection failure. This will keep the krb5kdc daemon from +continuing to run with a NULL LDAP context. + +Fixes: https://pagure.io/freeipa/issue/9422 + +Signed-off-by: Julien Rische +Reviewed-By: Alexander Bokovoy + +--- + +diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c +index 8da7543..83cb991 100644 +--- a/daemons/ipa-kdb/ipa_kdb_mspac.c ++++ b/daemons/ipa-kdb/ipa_kdb_mspac.c +@@ -401,27 +401,29 @@ static krb5_error_code ipadb_add_asserted_identity(struct ipadb_context *ipactx, + return 0; + } + +-static bool is_master_host(struct ipadb_context *ipactx, const char *fqdn) ++static krb5_error_code ++is_master_host(struct ipadb_context *ipactx, const char *fqdn, bool *result) + { +- int ret; ++ int err; + char *master_host_base = NULL; +- LDAPMessage *result = NULL; +- krb5_error_code err; ++ LDAPMessage *ldap_res = NULL; + +- ret = asprintf(&master_host_base, "cn=%s,cn=masters,cn=ipa,cn=etc,%s", ++ err = asprintf(&master_host_base, "cn=%s,cn=masters,cn=ipa,cn=etc,%s", + fqdn, ipactx->base); +- if (ret == -1) { +- return false; +- } ++ if (err == -1) ++ return ENOMEM; ++ + err = ipadb_simple_search(ipactx, master_host_base, LDAP_SCOPE_BASE, +- NULL, NULL, &result); ++ NULL, NULL, &ldap_res); + free(master_host_base); +- ldap_msgfree(result); +- if (err == 0) { +- return true; +- } ++ ldap_msgfree(ldap_res); ++ if (err != KRB5_KDB_NOENTRY && err != 0) ++ return err; ++ ++ if (result) ++ *result = err != KRB5_KDB_NOENTRY; + +- return false; ++ return 0; + } + + static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx, +@@ -692,9 +694,14 @@ static krb5_error_code ipadb_fill_info3(struct ipadb_context *ipactx, + if ((is_host || is_service)) { + /* it is either host or service, so get the hostname first */ + char *sep = strchr(info3->base.account_name.string, '/'); +- bool is_master = is_master_host( +- ipactx, +- sep ? sep + 1 : info3->base.account_name.string); ++ bool is_master; ++ ++ ret = is_master_host(ipactx, ++ sep ? sep + 1 : info3->base.account_name.string, ++ &is_master); ++ if (ret) ++ return ret; ++ + if (is_master) { + /* Well known RID of domain controllers group */ + if (info3->base.rid == 0) { + diff --git a/SOURCES/0008-ipatests-enable-firewall-rule-for-http-service-on-acme-client_rhbz#2230256.patch b/SOURCES/0008-ipatests-enable-firewall-rule-for-http-service-on-acme-client_rhbz#2230256.patch new file mode 100644 index 0000000..041905c --- /dev/null +++ b/SOURCES/0008-ipatests-enable-firewall-rule-for-http-service-on-acme-client_rhbz#2230256.patch @@ -0,0 +1,39 @@ +From f68468718c1e01df4a9180e17d7e24d961850e19 Mon Sep 17 00:00:00 2001 +From: Mohammad Rizwan +Date: Wed, 14 Jun 2023 17:32:02 +0530 +Subject: [PATCH] ipatests: enable firewall rule for http service on acme + client + +when system hardning done i.e in case of STIG, sometimes http challanges +can't be validated by CA if port 80 is not open. This fix enable it to facilitate +the communication. + +Signed-off-by: Mohammad Rizwan +Reviewed-By: Rob Crittenden +Reviewed-By: Florence Blanc-Renaud +--- + ipatests/test_integration/test_acme.py | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/ipatests/test_integration/test_acme.py b/ipatests/test_integration/test_acme.py +index c69e810da70..414fae8d751 100644 +--- a/ipatests/test_integration/test_acme.py ++++ b/ipatests/test_integration/test_acme.py +@@ -10,6 +10,7 @@ + + from ipalib.constants import IPA_CA_RECORD + from ipatests.test_integration.base import IntegrationTest ++from ipatests.pytest_ipa.integration.firewall import Firewall + from ipatests.pytest_ipa.integration import tasks + from ipatests.test_integration.test_caless import CALessBase, ipa_certs_cleanup + from ipaplatform.osinfo import osinfo +@@ -82,6 +83,9 @@ def prepare_acme_client(master, client): + acme_host = f'{IPA_CA_RECORD}.{master.domain.name}' + acme_server = f'https://{acme_host}/acme/directory' + ++ # enable firewall rule on client ++ Firewall(client).enable_services(["http", "https"]) ++ + # install acme client packages + if not skip_certbot_tests: + tasks.install_packages(client, ['certbot']) diff --git a/SOURCES/0009-User-plugin-improve-error-related-to-non-existing-idp_rhbz#2224572.patch b/SOURCES/0009-User-plugin-improve-error-related-to-non-existing-idp_rhbz#2224572.patch new file mode 100644 index 0000000..6109658 --- /dev/null +++ b/SOURCES/0009-User-plugin-improve-error-related-to-non-existing-idp_rhbz#2224572.patch @@ -0,0 +1,193 @@ +From 99aa03413421cf2839e89e10ca279ec19233dd01 Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Jul 20 2023 08:23:36 +0000 +Subject: User plugin: improve error related to non existing idp + + +The user and stageuser commands return the following error +when the user is created/updated with a non existing idp: +$ ipa user-add testuser --first test --last user --idp dummy +ipa: ERROR: no such entry + +The error is not descriptive enough and has been modified to +display instead: +$ ipa user-add testuser --first test --last user --idp dummy +ipa: ERROR: External IdP configuration dummy not found + +Fixes: https://pagure.io/freeipa/issue/9416 + +Signed-off-by: Florence Blanc-Renaud +Reviewed-By: Rob Crittenden + +--- + +diff --git a/ipaserver/plugins/baseuser.py b/ipaserver/plugins/baseuser.py +index 73b76d3..ba5f9b7 100644 +--- a/ipaserver/plugins/baseuser.py ++++ b/ipaserver/plugins/baseuser.py +@@ -708,7 +708,11 @@ class baseuser_mod(LDAPUpdate): + if 'ipaidpuser' not in obj_classes: + entry_attrs['objectclass'].append('ipaidpuser') + +- answer = self.api.Object['idp'].get_dn_if_exists(cl) ++ try: ++ answer = self.api.Object['idp'].get_dn_if_exists(cl) ++ except errors.NotFound: ++ reason = "External IdP configuration {} not found" ++ raise errors.NotFound(reason=_(reason).format(cl)) + entry_attrs['ipaidpconfiglink'] = answer + + # Note: we could have used the method add_missing_object_class +diff --git a/ipaserver/plugins/stageuser.py b/ipaserver/plugins/stageuser.py +index 51438a8..852e51b 100644 +--- a/ipaserver/plugins/stageuser.py ++++ b/ipaserver/plugins/stageuser.py +@@ -404,7 +404,11 @@ class stageuser_add(baseuser_add): + if 'ipaidpuser' not in entry_attrs['objectclass']: + entry_attrs['objectclass'].append('ipaidpuser') + +- answer = self.api.Object['idp'].get_dn_if_exists(cl) ++ try: ++ answer = self.api.Object['idp'].get_dn_if_exists(cl) ++ except errors.NotFound: ++ reason = "External IdP configuration {} not found" ++ raise errors.NotFound(reason=_(reason).format(cl)) + entry_attrs['ipaidpconfiglink'] = answer + + self.pre_common_callback(ldap, dn, entry_attrs, attrs_list, *keys, +diff --git a/ipaserver/plugins/user.py b/ipaserver/plugins/user.py +index 643b44f..a337e1f 100644 +--- a/ipaserver/plugins/user.py ++++ b/ipaserver/plugins/user.py +@@ -638,7 +638,11 @@ class user_add(baseuser_add): + if 'ipaidpuser' not in entry_attrs['objectclass']: + entry_attrs['objectclass'].append('ipaidpuser') + +- answer = self.api.Object['idp'].get_dn_if_exists(rcl) ++ try: ++ answer = self.api.Object['idp'].get_dn_if_exists(rcl) ++ except errors.NotFound: ++ reason = "External IdP configuration {} not found" ++ raise errors.NotFound(reason=_(reason).format(rcl)) + entry_attrs['ipaidpconfiglink'] = answer + + self.pre_common_callback(ldap, dn, entry_attrs, attrs_list, *keys, + +From dbcbe9a39c99008c6858bab53e2807b7bf01ba65 Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Jul 20 2023 08:23:36 +0000 +Subject: xmlrpc tests: add a test for user plugin with non-existing idp + + +Add new tests checking the error returned for +ipa user-add ... --idp nonexistingidp +ipa user-mod ... --idp nonexistingidp +ipa stageuser-add ... --idp nonexistingidp +ipa stageuser-mod ... --idp nonexistingidp + +The expected error message is: +ipa: ERROR: External IdP configuration nonexistingidp not found + +Related: https://pagure.io/freeipa/issue/9416 + +Signed-off-by: Florence Blanc-Renaud +Reviewed-By: Rob Crittenden + +--- + +diff --git a/ipatests/test_xmlrpc/test_stageuser_plugin.py b/ipatests/test_xmlrpc/test_stageuser_plugin.py +index 394015f..9ae5561 100644 +--- a/ipatests/test_xmlrpc/test_stageuser_plugin.py ++++ b/ipatests/test_xmlrpc/test_stageuser_plugin.py +@@ -39,6 +39,8 @@ gid = u'456' + invalidrealm1 = u'suser1@NOTFOUND.ORG' + invalidrealm2 = u'suser1@BAD@NOTFOUND.ORG' + ++nonexistentidp = 'IdPDoesNotExist' ++ + invaliduser1 = u'+tuser1' + invaliduser2 = u'tuser1234567890123456789012345678901234567890' + invaliduser3 = u'1234' +@@ -431,6 +433,15 @@ class TestCreateInvalidAttributes(XMLRPC_test): + invalidrealm2))): + command() + ++ def test_create_invalid_idp(self, stageduser): ++ stageduser.ensure_missing() ++ command = stageduser.make_create_command( ++ options={u'ipaidpconfiglink': nonexistentidp}) ++ with raises_exact(errors.NotFound( ++ reason="External IdP configuration {} not found".format( ++ nonexistentidp))): ++ command() ++ + + @pytest.mark.tier1 + class TestUpdateInvalidAttributes(XMLRPC_test): +@@ -466,6 +477,15 @@ class TestUpdateInvalidAttributes(XMLRPC_test): + message=u'invalid \'gidnumber\': must be at least 1')): + command() + ++ def test_update_invalididp(self, stageduser): ++ stageduser.ensure_exists() ++ command = stageduser.make_update_command( ++ updates={u'ipaidpconfiglink': nonexistentidp}) ++ with raises_exact(errors.NotFound( ++ reason="External IdP configuration {} not found".format( ++ nonexistentidp))): ++ command() ++ + + @pytest.mark.tier1 + class TestActive(XMLRPC_test): +diff --git a/ipatests/test_xmlrpc/test_user_plugin.py b/ipatests/test_xmlrpc/test_user_plugin.py +index 8ac19a4..baa2867 100644 +--- a/ipatests/test_xmlrpc/test_user_plugin.py ++++ b/ipatests/test_xmlrpc/test_user_plugin.py +@@ -86,6 +86,8 @@ expired_expiration_string = "1991-12-07T19:54:13Z" + # Date in ISO format (2013-12-10T12:00:00) + isodate_re = re.compile(r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$') + ++nonexistentidp = 'IdPDoesNotExist' ++ + + @pytest.fixture(scope='class') + def user_min(request, xmlrpc_setup): +@@ -542,6 +544,18 @@ class TestUpdate(XMLRPC_test): + command() + user.delete() + ++ def test_update_invalid_idp(self, user): ++ """ Test user-mod --idp with a non-existent idp """ ++ user.ensure_exists() ++ command = user.make_update_command( ++ updates=dict(ipaidpconfiglink=nonexistentidp) ++ ) ++ with raises_exact(errors.NotFound( ++ reason="External IdP configuration {} not found".format( ++ nonexistentidp) ++ )): ++ command() ++ + + @pytest.mark.tier1 + class TestCreate(XMLRPC_test): +@@ -770,6 +784,17 @@ class TestCreate(XMLRPC_test): + user_radius.check_create(result) + user_radius.delete() + ++ def test_create_with_invalididp(self): ++ testuser = UserTracker( ++ name='idpuser', givenname='idp', sn='user', ++ ipaidpconfiglink=nonexistentidp ++ ) ++ with raises_exact(errors.NotFound( ++ reason="External IdP configuration {} not found".format( ++ nonexistentidp) ++ )): ++ testuser.create() ++ + + @pytest.mark.tier1 + class TestUserWithGroup(XMLRPC_test): + diff --git a/SOURCES/0010-Prevent-admin-user-from-being-deleted_rhbz#1921181.patch b/SOURCES/0010-Prevent-admin-user-from-being-deleted_rhbz#1921181.patch new file mode 100644 index 0000000..be8d65f --- /dev/null +++ b/SOURCES/0010-Prevent-admin-user-from-being-deleted_rhbz#1921181.patch @@ -0,0 +1,169 @@ +From f215d3f45396fa29bdd69f56096b50842df14908 Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Aug 01 2023 22:03:03 +0000 +Subject: Prevent the admin user from being deleted + + +admin is required for trust operations + +Note that testing for removing the last member is now +irrelevant because admin must always exist so the test +for it was removed, but the code check remains. It is done +after the protected member check. + +Fixes: https://pagure.io/freeipa/issue/8878 + +Signed-off-by: Rob Crittenden +Reviewed-By: Alexander Bokovoy + +--- + +diff --git a/ipaserver/plugins/user.py b/ipaserver/plugins/user.py +index a337e1f..6f5e349 100644 +--- a/ipaserver/plugins/user.py ++++ b/ipaserver/plugins/user.py +@@ -138,14 +138,23 @@ MEMBEROF_ADMINS = "(memberOf={})".format( + ) + + NOT_MEMBEROF_ADMINS = '(!{})'.format(MEMBEROF_ADMINS) ++PROTECTED_USERS = ('admin',) + + + def check_protected_member(user, protected_group_name=u'admins'): + ''' +- Ensure the last enabled member of a protected group cannot be deleted or +- disabled by raising LastMemberError. ++ Ensure admin and the last enabled member of a protected group cannot ++ be deleted or disabled by raising ProtectedEntryError or ++ LastMemberError as appropriate. + ''' + ++ if user in PROTECTED_USERS: ++ raise errors.ProtectedEntryError( ++ label=_("user"), ++ key=user, ++ reason=_("privileged user"), ++ ) ++ + # Get all users in the protected group + result = api.Command.user_find(in_group=protected_group_name) + +@@ -868,6 +877,12 @@ class user_mod(baseuser_mod): + + def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + dn, oc = self.obj.get_either_dn(*keys, **options) ++ if options.get('rename') and keys[-1] in PROTECTED_USERS: ++ raise errors.ProtectedEntryError( ++ label=_("user"), ++ key=keys[-1], ++ reason=_("privileged user"), ++ ) + if 'objectclass' not in entry_attrs and 'rename' not in options: + entry_attrs.update({'objectclass': oc}) + self.pre_common_callback(ldap, dn, entry_attrs, attrs_list, *keys, +diff --git a/ipatests/test_xmlrpc/test_user_plugin.py b/ipatests/test_xmlrpc/test_user_plugin.py +index baa2867..df105a2 100644 +--- a/ipatests/test_xmlrpc/test_user_plugin.py ++++ b/ipatests/test_xmlrpc/test_user_plugin.py +@@ -978,22 +978,32 @@ class TestManagers(XMLRPC_test): + + @pytest.mark.tier1 + class TestAdmins(XMLRPC_test): +- def test_remove_original_admin(self): +- """ Try to remove the only admin """ ++ def test_delete_admin(self): ++ """ Try to delete the protected admin user """ + tracker = Tracker() +- command = tracker.make_command('user_del', [admin1]) ++ command = tracker.make_command('user_del', admin1) + +- with raises_exact(errors.LastMemberError( +- key=admin1, label=u'group', container=admin_group)): ++ with raises_exact(errors.ProtectedEntryError(label=u'user', ++ key=admin1, reason='privileged user')): ++ command() ++ ++ def test_rename_admin(self): ++ """ Try to rename the admin user """ ++ tracker = Tracker() ++ command = tracker.make_command('user_mod', admin1, ++ **dict(rename=u'newadmin')) ++ ++ with raises_exact(errors.ProtectedEntryError(label=u'user', ++ key=admin1, reason='privileged user')): + command() + + def test_disable_original_admin(self): +- """ Try to disable the only admin """ ++ """ Try to disable the original admin """ + tracker = Tracker() + command = tracker.make_command('user_disable', admin1) + +- with raises_exact(errors.LastMemberError( +- key=admin1, label=u'group', container=admin_group)): ++ with raises_exact(errors.ProtectedEntryError(label=u'user', ++ key=admin1, reason='privileged user')): + command() + + def test_create_admin2(self, admin2): +@@ -1011,21 +1021,11 @@ class TestAdmins(XMLRPC_test): + admin2.disable() + tracker = Tracker() + +- with raises_exact(errors.LastMemberError( +- key=admin1, label=u'group', container=admin_group)): ++ with raises_exact(errors.ProtectedEntryError(label=u'user', ++ key=admin1, reason='privileged user')): + tracker.run_command('user_disable', admin1) +- with raises_exact(errors.LastMemberError( +- key=admin1, label=u'group', container=admin_group)): +- tracker.run_command('user_del', admin1) + admin2.delete() + +- with raises_exact(errors.LastMemberError( +- key=admin1, label=u'group', container=admin_group)): +- tracker.run_command('user_disable', admin1) +- with raises_exact(errors.LastMemberError( +- key=admin1, label=u'group', container=admin_group)): +- tracker.run_command('user_del', admin1) +- + + @pytest.mark.tier1 + class TestPreferredLanguages(XMLRPC_test): + +From 7d62d84bdd3c2acd2f4bf70bb5fabf14c72e8ee7 Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Aug 08 2023 14:50:32 +0000 +Subject: ipatests: update expected webui msg for admin deletion + + +The deletion of the admin is now forbidden (even if it is +not the last member of the admins group) and the error +message has changed from "admin cannot be deleted or +disabled because it is the last member of group admins" +to " user admin cannot be deleted/modified: privileged user". + +Update the expected message in the webui test. + +Related: https://pagure.io/freeipa/issue/8878 + +Signed-off-by: Florence Blanc-Renaud +Reviewed-By: Alexander Bokovoy + +--- + +diff --git a/ipatests/test_webui/test_user.py b/ipatests/test_webui/test_user.py +index 8d44fbd..a8a92d0 100644 +--- a/ipatests/test_webui/test_user.py ++++ b/ipatests/test_webui/test_user.py +@@ -50,8 +50,7 @@ INV_FIRSTNAME = ("invalid 'first': Leading and trailing spaces are " + FIELD_REQ = 'Required field' + ERR_INCLUDE = 'may only include letters, numbers, _, -, . and $' + ERR_MISMATCH = 'Passwords must match' +-ERR_ADMIN_DEL = ('admin cannot be deleted or disabled because it is the last ' +- 'member of group admins') ++ERR_ADMIN_DEL = ('user admin cannot be deleted/modified: privileged user') + USR_EXIST = 'user with name "{}" already exists' + ENTRY_EXIST = 'This entry already exists' + ACTIVE_ERR = 'active user with name "{}" already exists' + diff --git a/SOURCES/0011-Fix-memory-leak-in-the-OTP-last-token-plugin_rhbz#2227783.patch b/SOURCES/0011-Fix-memory-leak-in-the-OTP-last-token-plugin_rhbz#2227783.patch new file mode 100644 index 0000000..773b553 --- /dev/null +++ b/SOURCES/0011-Fix-memory-leak-in-the-OTP-last-token-plugin_rhbz#2227783.patch @@ -0,0 +1,114 @@ +From 9438ce9207445e4ad4a9c7bdf0c9e569cabac571 Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Aug 01 2023 06:07:06 +0000 +Subject: Fix memory leak in the OTP last token plugin + + +Three memory leaks are addressed: + +1. String values retrieved from the pblock need to be manually +freed. + +2. The list of objectclasses retreived from the pblock need to be +freed. + +3. Internal search results need to be freed. + +Fixes: https://pagure.io/freeipa/issue/9403 + +Signed-off-by: Rob Crittenden +Reviewed-By: Rafael Guterres Jeffman +Reviewed-By: Alexander Bokovoy + +--- + +diff --git a/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c b/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c +index b7a2ba7..11106b2 100644 +--- a/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c ++++ b/daemons/ipa-slapi-plugins/ipa-otp-lasttoken/ipa_otp_lasttoken.c +@@ -54,7 +54,7 @@ void *ipa_otp_lasttoken_plugin_id; + + static bool entry_is_token(Slapi_Entry *entry) + { +- char **ocls; ++ char **ocls = NULL; + + ocls = slapi_entry_attr_get_charray(entry, SLAPI_ATTR_OBJECTCLASS); + for (size_t i = 0; ocls != NULL && ocls[i] != NULL; i++) { +@@ -64,6 +64,7 @@ static bool entry_is_token(Slapi_Entry *entry) + } + } + ++ slapi_ch_array_free(ocls); + return false; + } + +@@ -138,7 +139,8 @@ static bool is_pwd_enabled(const char *user_dn) + static bool is_allowed(Slapi_PBlock *pb, Slapi_Entry *entry) + { + Slapi_DN *target_sdn = NULL; +- const char *bind_dn; ++ char *bind_dn; ++ bool rv = false; + + /* Ignore internal operations. */ + if (slapi_op_internal(pb)) +@@ -147,23 +149,35 @@ static bool is_allowed(Slapi_PBlock *pb, Slapi_Entry *entry) + /* Load parameters. */ + (void) slapi_pblock_get(pb, SLAPI_TARGET_SDN, &target_sdn); + (void) slapi_pblock_get(pb, SLAPI_CONN_DN, &bind_dn); +- if (target_sdn == NULL || bind_dn == NULL) { +- LOG_FATAL("Missing parameters!\n"); +- return false; ++ if (bind_dn == NULL) { ++ LOG_FATAL("bind_dn parameter missing!\n"); ++ goto done; ++ } ++ if (target_sdn == NULL) { ++ LOG_FATAL("target_sdn parameter missing!\n"); ++ goto done; + } + + if (entry != NULL + ? !entry_is_token(entry) +- : !sdn_in_otp_container(target_sdn)) +- return true; ++ : !sdn_in_otp_container(target_sdn)) { ++ rv = true; ++ goto done; ++ } + +- if (!sdn_is_only_enabled_token(target_sdn, bind_dn)) +- return true; ++ if (!sdn_is_only_enabled_token(target_sdn, bind_dn)) { ++ rv = true; ++ goto done; ++ } + +- if (is_pwd_enabled(bind_dn)) +- return true; ++ if (is_pwd_enabled(bind_dn)) { ++ rv = true; ++ goto done; ++ } + +- return false; ++done: ++ slapi_ch_free_string(&bind_dn); ++ return rv; + } + + static inline int send_error(Slapi_PBlock *pb, int rc, const char *errstr) +diff --git a/daemons/ipa-slapi-plugins/libotp/otp_token.c b/daemons/ipa-slapi-plugins/libotp/otp_token.c +index a3cbfb0..4be4ede 100644 +--- a/daemons/ipa-slapi-plugins/libotp/otp_token.c ++++ b/daemons/ipa-slapi-plugins/libotp/otp_token.c +@@ -398,6 +398,7 @@ static struct otp_token **find(const struct otp_config *cfg, const char *user_dn + } + + error: ++ slapi_free_search_results_internal(pb); + slapi_pblock_destroy(pb); + return tokens; + } + diff --git a/SOURCES/0012-ipatests-fix-test_topology_rhbz#2232351.patch b/SOURCES/0012-ipatests-fix-test_topology_rhbz#2232351.patch new file mode 100644 index 0000000..e5533c3 --- /dev/null +++ b/SOURCES/0012-ipatests-fix-test_topology_rhbz#2232351.patch @@ -0,0 +1,58 @@ +From fdaad3a45f5674876fd3f6cc7ad1e916ebfc7080 Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Aug 14 2023 13:02:20 +0000 +Subject: ipatests: fix test_topology + + +The test TestTopologyOptions::test_add_remove_segment is +randomly failing downstream. Test scenario: +- create a line topology master <-> repl1 <-> repl2 +- create user on master +- wait for repl success on master +- check that the user is seen on repl2 + +The test waits for replication to complete on the master but +it should also wait for the replication to complete on repl1 +before checking the user presence on repl2. + +Signed-off-by: Florence Blanc-Renaud +Reviewed-By: Anuja More + +--- + +diff --git a/ipatests/test_integration/test_topology.py b/ipatests/test_integration/test_topology.py +index 8a240fa..618c9d5 100644 +--- a/ipatests/test_integration/test_topology.py ++++ b/ipatests/test_integration/test_topology.py +@@ -124,6 +124,9 @@ class TestTopologyOptions(IntegrationTest): + self.replicas[0], + self.replicas[1]) + assert err == "", err ++ # At this point we have replicas[1] <-> master <-> replicas[0] ++ # ^--------------------------^ ++ + # Make sure the new segment is shown by `ipa topologysegment-find` + result1 = self.master.run_command(['ipa', 'topologysegment-find', + DOMAIN_SUFFIX_NAME]).stdout_text +@@ -137,9 +140,12 @@ class TestTopologyOptions(IntegrationTest): + deleteme = find_segment(self.master, self.replicas[1]) + returncode, error = tasks.destroy_segment(self.master, deleteme) + assert returncode == 0, error ++ # At this point we have master <-> replicas[0] <-> replicas[1] ++ + # Wait till replication ends and make sure replica1 does not have + # segment that was deleted on master + master_ldap = self.master.ldap_connect() ++ repl_ldap = self.replicas[0].ldap_connect() + tasks.wait_for_replication(master_ldap) + result3 = self.replicas[0].run_command(['ipa', 'topologysegment-find', + DOMAIN_SUFFIX_NAME]).stdout_text +@@ -150,6 +156,7 @@ class TestTopologyOptions(IntegrationTest): + '--first', 'test', + '--last', 'user']) + tasks.wait_for_replication(master_ldap) ++ tasks.wait_for_replication(repl_ldap) + result4 = self.replicas[1].run_command(['ipa', 'user-find']) + assert('someuser' in result4.stdout_text), 'User not found: someuser' + # We end up having a line topology: master <-> replica1 <-> replica2 + diff --git a/SOURCES/0013-Installer-activate-nss-and-pam-services-in-sssd.conf_rhbz#2216532.patch b/SOURCES/0013-Installer-activate-nss-and-pam-services-in-sssd.conf_rhbz#2216532.patch new file mode 100644 index 0000000..64a634c --- /dev/null +++ b/SOURCES/0013-Installer-activate-nss-and-pam-services-in-sssd.conf_rhbz#2216532.patch @@ -0,0 +1,40 @@ +From f38eefd9f7e54470de7c707782114b17aac8762a Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Aug 16 2023 15:25:34 +0000 +Subject: Installer: activate nss and pam services in sssd.conf + + +If there is already a sssd.conf file before the installer is +executed, the nss and pam services may not be enabled by the +installer. This happens for instance if the machine is hardened +for STIG and sssd.conf does not define services=... in the +[sssd] section. + +The consequence is that trust cannot be established with an AD +domain. + +The installer must enable nss and pam services even if there is +a pre-existing sssd.conf file. + +Fixes: https://pagure.io/freeipa/issue/9427 + +Signed-off-by: Florence Blanc-Renaud +Reviewed-By: Alexander Bokovoy + +--- + +diff --git a/ipaclient/install/client.py b/ipaclient/install/client.py +index ef29a2c..07d62a7 100644 +--- a/ipaclient/install/client.py ++++ b/ipaclient/install/client.py +@@ -969,6 +969,9 @@ def configure_sssd_conf( + nss_service.set_option('memcache_timeout', 600) + sssdconfig.save_service(nss_service) + ++ sssd_enable_service(sssdconfig, 'nss') ++ sssd_enable_service(sssdconfig, 'pam') ++ + domain.set_option('ipa_domain', cli_domain) + domain.set_option('ipa_hostname', client_hostname) + if cli_domain.lower() != cli_realm.lower(): + diff --git a/SOURCES/1002-Revert-freeipa.spec-depend-on-bind-dnssec-utils.patch b/SOURCES/1002-Revert-freeipa.spec-depend-on-bind-dnssec-utils.patch index fe9eba6..e1a74ff 100644 --- a/SOURCES/1002-Revert-freeipa.spec-depend-on-bind-dnssec-utils.patch +++ b/SOURCES/1002-Revert-freeipa.spec-depend-on-bind-dnssec-utils.patch @@ -15,7 +15,7 @@ diff --git a/freeipa.spec.in b/freeipa.spec.in index 8f5c370e5..e20edb7bc 100755 --- a/freeipa.spec.in +++ b/freeipa.spec.in -@@ -585,11 +585,9 @@ Requires: %{name}-server = %{version}-%{release} +@@ -576,11 +576,9 @@ Requires: %{name}-server = %{version}-%{release} Requires: bind-dyndb-ldap >= 11.2-2 Requires: bind >= %{bind_version} Requires: bind-utils >= %{bind_version} @@ -32,16 +32,15 @@ diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py index 7d21367ec..42a47f1df 100644 --- a/ipaplatform/base/paths.py +++ b/ipaplatform/base/paths.py -@@ -258,8 +258,7 @@ class BasePathNamespace: +@@ -259,7 +259,6 @@ class BasePathNamespace: IPA_PKI_RETRIEVE_KEY = "/usr/libexec/ipa/ipa-pki-retrieve-key" IPA_HTTPD_PASSWD_READER = "/usr/libexec/ipa/ipa-httpd-pwdreader" IPA_PKI_WAIT_RUNNING = "/usr/libexec/ipa/ipa-pki-wait-running" - DNSSEC_KEYFROMLABEL = "/usr/sbin/dnssec-keyfromlabel" -- DNSSEC_KEYFROMLABEL_9_17 = "/usr/bin/dnssec-keyfromlabel" + DNSSEC_KEYFROMLABEL = "/usr/sbin/dnssec-keyfromlabel-pkcs11" +- DNSSEC_KEYFROMLABEL_9_17 = "/usr/bin/dnssec-keyfromlabel" GETSEBOOL = "/usr/sbin/getsebool" GROUPADD = "/usr/sbin/groupadd" - USERMOD = "/usr/sbin/usermod" diff --git a/ipaplatform/fedora/paths.py b/ipaplatform/fedora/paths.py index 4e993c063..92a948966 100644 --- a/ipaplatform/fedora/paths.py diff --git a/SOURCES/1004-Revert-DNSResolver-Fix-use-of-nameservers-with-ports.patch b/SOURCES/1004-Revert-DNSResolver-Fix-use-of-nameservers-with-ports.patch index d5fe2d3..ef09a82 100644 --- a/SOURCES/1004-Revert-DNSResolver-Fix-use-of-nameservers-with-ports.patch +++ b/SOURCES/1004-Revert-DNSResolver-Fix-use-of-nameservers-with-ports.patch @@ -4,20 +4,20 @@ Date: Mon, 19 Dec 2022 14:57:03 -0300 Subject: [PATCH] Revert "DNSResolver: Fix use of nameservers with ports" This reverts commit 5e2e4664aec641886923c2bec61ce25b96edb62a. ---- - ipapython/dnsutil.py | 41 ------------------------- - ipatests/test_ipapython/test_dnsutil.py | 40 ------------------------ - 2 files changed, 81 deletions(-) diff --git a/ipapython/dnsutil.py b/ipapython/dnsutil.py index 58de365ab..4baeaf8cc 100644 ---- a/ipapython/dnsutil.py -+++ b/ipapython/dnsutil.py -@@ -144,47 +144,6 @@ class DNSResolver(dns.resolver.Resolver): +--- a/ipapython/dnsutil.py 2023-05-19 05:12:52.471239297 -0300 ++++ b/ipapython/dnsutil.py 2023-05-24 12:20:13.588867053 -0300 +@@ -145,55 +145,6 @@ nameservers.remove(ipv4_loopback) self.nameservers = nameservers -- @dns.resolver.Resolver.nameservers.setter +- @property +- def nameservers(self): +- return self._nameservers +- +- @nameservers.setter - def nameservers(self, nameservers): - """ - *nameservers*, a ``list`` of nameservers with optional ports: @@ -54,7 +54,11 @@ index 58de365ab..4baeaf8cc 100644 - nameservers = _nameservers - - # Call dns.resolver.Resolver.nameservers setter -- dns.resolver.Resolver.nameservers.__set__(self, nameservers) +- if hasattr(dns.resolver.Resolver, "nameservers"): +- dns.resolver.Resolver.nameservers.__set__(self, nameservers) +- else: +- # old dnspython (<2) doesn't have 'nameservers' property +- self._nameservers = nameservers - # Set nameserver_ports after successfull call to setter - self.nameserver_ports = nameserver_ports - @@ -62,23 +66,29 @@ index 58de365ab..4baeaf8cc 100644 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 09463c69d..5e7a46197 100644 +index 9070d89ad..5e7a46197 100644 --- a/ipatests/test_ipapython/test_dnsutil.py +++ b/ipatests/test_ipapython/test_dnsutil.py -@@ -101,43 +101,3 @@ class TestSortURI: +@@ -101,48 +101,3 @@ 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() +- @pytest.fixture(name="res") +- def resolver(self): +- """Resolver that doesn't read /etc/resolv.conf +- +- /etc/resolv.conf is not mandatory on systems +- """ +- return dnsutil.DNSResolver(configure=False) +- +- def test_nameservers(self, res): - 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() +- def test_nameservers_with_ports(self, res): - 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} @@ -87,8 +97,7 @@ index 09463c69d..5e7a46197 100644 - 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() +- def test_nameservers_with_bad_ports(self, res): - try: - res.nameservers = ["4.4.4.4 port a"] - except ValueError: @@ -109,6 +118,3 @@ index 09463c69d..5e7a46197 100644 - pass - else: - pytest.fail("No fail on bad port 65536") --- -2.38.1 - diff --git a/SOURCES/freeipa-4.9.11.tar.gz.asc b/SOURCES/freeipa-4.9.11.tar.gz.asc deleted file mode 100644 index 47ddb7d..0000000 --- a/SOURCES/freeipa-4.9.11.tar.gz.asc +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iQIzBAABCAAdFiEE11Z2TU1+KXxtrRFyaYdvcqbi008FAmOA8kcACgkQaYdvcqbi -00887g/9GTvueJCypiuTqxKsbkTbWamOyH3W+AqtHw9Ff+wM/hnkSloGizhQ4EZZ -4Zs1e6bfM1pGXT7DXU9WbiYtcVtUhY5l9SnT9moCMaG1z4aB7z9UCxsqsSCuy3bG -KQq6AO2z4DaqHiz6ez3QXi+MUCNnPziWmS3bLdDCrTK0PNxqiMPIotlXMgVFgDL7 -go/TAUvUL27zH4ELvG4parSGEKVEqe//RzXklOwGrInyj/4u42x7lUdO2ugOolCI -wNod8v+NWQWVgxNyhfTjP5VBZzO9wkGx4xruF2cAjVdjnIUGcG0FR3hI/bpi7Lyv -EmIozbQMK92MLel63E7Z/d5Jxfmuw/n1t5NrgSth+9hhWnBEpiaKkD2zAmUATqHf -+y4mbrtajmjzewEnfUnQfCvSLDPyTpnQKkRY8hUvk7u/J+/ZFWMQl9RdGNw3M0Zr -WrsqkKLK/n5IOHYHb/lBRaUidssKjQYFIvyNfHDP/lu6iiyLOpi5MIdk9BakO5wc -oDMk3w9xY7tPPmoesW40BThnAdOR9U4aad8zVvOxhMfzAYRwu95HGQoHnk7/rNut -IfzMZVjVTLQ8gyApcBlWzu/buiOoEXTKaMyzs0S9RMptknj5Xf0CGRz3bVrZRfJd -umyhD6/rNk3eZW/yEIv3IqFev0h1txTBPSTlczYUIz6uc7nx82E= -=8YVm ------END PGP SIGNATURE----- diff --git a/SOURCES/freeipa-4.9.12.tar.gz.asc b/SOURCES/freeipa-4.9.12.tar.gz.asc new file mode 100644 index 0000000..699aa14 --- /dev/null +++ b/SOURCES/freeipa-4.9.12.tar.gz.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCAAdFiEE11Z2TU1+KXxtrRFyaYdvcqbi008FAmRnL+gACgkQaYdvcqbi +00/1Gg/8CFABojXZyUkQnWeaHdrFeHeE+DW2qTs9Wr/TQwF67fYkh7lj3p+WqMlD +kMMNAfLn4wUnJNDMv64QlE6RAz71KetQlQt+mZQVT9M0nDepLhBw86qmNbJj611J ++2B79hzNLT8tmOf9NyLRJbFp3QebSPELX9hycPj1Ovd1tr/61tcwcNzE6ZLrX5vb +IPkCT2bo+6MceIsR50tTRxxK6J9jFYX73PjHJ5Ix7ssDf4vg2OBRTwUdLeZAkWlA +q+0bPPp+F3PWLhnSs+vIs5plHUI/hcGCt9pTvw/d6jUUxuwZadGGbRZSyDN7aj2Q +zEXeZsCtOSk5cx65lWHl+7TTyVvCoemeZPZ92EiCtVJfiuK3/6a/WFWanBZoO0E3 +N0p6HUcvIRPrEj0nQwH2vr0zkfSPA4g30k+Q9qeP3ArN+i+5OFfuiwiqk1AIJ2rv +ERhBRryOaNeiVpYghMQdtacWP/qQunfH6VdhA61Q089/lhomGeSytQI+fV4TXOhV +ldV7dftaWpQT3QYWSsKzoiHpyjIwOA8dBvQF2YDX7LNmeO/hj4ToFp00CVCWdb0j +MHs2X9p42kkhw2oZOf3GNyNvpybxUv59ER4YDEHbj8+iZyVjiqfcp71373DqpieW +iGjB3Wc0gO3cdYk3Mdl0SgkD7k0U9iwwh7qJeqqUYT3gKf9mqbY= +=dT0o +-----END PGP SIGNATURE----- diff --git a/SPECS/ipa.spec b/SPECS/ipa.spec index 4aab5cf..4db2e66 100644 --- a/SPECS/ipa.spec +++ b/SPECS/ipa.spec @@ -64,7 +64,7 @@ %if 0%{?rhel} %global package_name ipa %global alt_name freeipa -%global krb5_version 1.18.2-2 +%global krb5_version 1.18.2-25 %global krb5_kdb_version 8.0 # 0.7.16: https://github.com/drkjam/netaddr/issues/71 %global python_netaddr_version 0.7.19 @@ -176,7 +176,7 @@ # Work-around fact that RPM SPEC parser does not accept # "Version: @VERSION@" in freeipa.spec.in used for Autoconf string replacement -%define IPA_VERSION 4.9.11 +%define IPA_VERSION 4.9.12 # Release candidate version -- uncomment with one percent for RC versions #%%global rc_version %%nil %define AT_SIGN @ @@ -189,7 +189,7 @@ Name: %{package_name} Version: %{IPA_VERSION} -Release: 5%{?rc_version:.%rc_version}%{?dist} +Release: 8%{?rc_version:.%rc_version}%{?dist} Summary: The Identity, Policy and Audit system License: GPLv3+ @@ -209,13 +209,19 @@ Source1: https://releases.pagure.org/freeipa/freeipa-%{version}%{?rc_vers # RHEL spec file only: START %if %{NON_DEVELOPER_BUILD} %if 0%{?rhel} >= 8 -Patch0001: 0001-updates-fix-memberManager-ACI-to-allow-managers-from-a-specified-group_rhbz#2056009.patch -Patch0002: 0002-trust-add-handle-missing-msSFU30MaxGidNumber_rhbz#2162355.patch -Patch0003: 0003-Backport-latest-test-fixes-python3-ipatests_rhbz#2166929.patch -Patch0004: 0004-server-install-remove-error-log-about-missing-bkup-file_rhbz#2160389.patch -Patch0005: 0005-automember-rebuild-add-a-notice-about-high-CPU-usage_rhbz#2018198.patch -Patch0006: 0006-ipa-kdb-PAC-consistency-checker-needs-to-handle-child-domains-as-well_rhbz#2166324.patch -Patch0007: 0007-Wipe-the-ipa-ca-DNS-record-when-updating-system-records_rhbz#2158775.patch +Patch0001: 0001-user-or-group-name-explain-the-supported-format_rhbz#2150217.patch +Patch0002: 0002-Use-the-python-cryptography-parser-directly-in-cert-find_rhbz#2164349.patch +Patch0003: 0003-Upgrade-add-PKI-drop-in-file-if-missing_rhbz#2215336.patch +Patch0004: 0004-Upgrade-fix-replica-agreement_rhbz#2216551.patch +Patch0005: 0005-OTP-fix-data-type-to-avoid-endianness-issue_rhbz#2218293.patch +Patch0006: 0006-Backport-test-updates-8-9-release_rhbz#2218847.patch +Patch0007: 0007-ipa-kdb-fix-error-handling-of-is_master_host_rhbz#2214638.patch +Patch0008: 0008-ipatests-enable-firewall-rule-for-http-service-on-acme-client_rhbz#2230256.patch +Patch0009: 0009-User-plugin-improve-error-related-to-non-existing-idp_rhbz#2224572.patch +Patch0010: 0010-Prevent-admin-user-from-being-deleted_rhbz#1921181.patch +Patch0011: 0011-Fix-memory-leak-in-the-OTP-last-token-plugin_rhbz#2227783.patch +Patch0012: 0012-ipatests-fix-test_topology_rhbz#2232351.patch +Patch0013: 0013-Installer-activate-nss-and-pam-services-in-sssd.conf_rhbz#2216532.patch Patch1001: 1001-Change-branding-to-IPA-and-Identity-Management.patch Patch1002: 1002-Revert-freeipa.spec-depend-on-bind-dnssec-utils.patch Patch1003: 1003-webui-IdP-Remove-arrow-notation-due-to-uglify-js-lim.patch @@ -229,8 +235,8 @@ Patch1004: 1004-Revert-DNSResolver-Fix-use-of-nameservers-with-ports.patch %endif # RHEL spec file only: END -## For the timestamp trick in patch application -#BuildRequires: diffstat +# For the timestamp trick in patch application +BuildRequires: diffstat BuildRequires: openldap-devel # For KDB DAL version, make explicit dependency so that increase of version @@ -673,6 +679,7 @@ Requires: jansson %endif Requires: sssd-ipa >= %{sssd_version} Requires: sssd-idp >= %{sssd_version} +Requires: sssd-krb5 >= %{sssd_version} Requires: certmonger >= %{certmonger_version} Requires: nss-tools >= %{nss_version} Requires: bind-utils @@ -952,8 +959,22 @@ Custom SELinux policy module for FreeIPA %prep +# Update timestamps on the files touched by a patch, to avoid non-equal +# .pyc/.pyo files across the multilib peers within a build, where "Level" +# is the patch prefix option (e.g. -p1) +# Taken from specfile for sssd and python-simplejson +UpdateTimestamps() { + Level=$1 + PatchFile=$2 -%autosetup -n freeipa-%{version}%{?rc_version} -N -p1 + # Locate the affected files: + for f in $(diffstat $Level -l $PatchFile); do + # Set the files to have the same timestamp as that of the patch: + touch -c -r $PatchFile $f + done +} + +%setup -n freeipa-%{version}%{?rc_version} -q # To allow proper application patches to the stripped po files, strip originals pushd po @@ -963,8 +984,10 @@ for i in *.po ; do done popd -%autopatch -p1 - +for p in %patches ; do + %__patch -p1 -i $p + UpdateTimestamps -p1 $p +done %build # PATH is workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1005235 @@ -1217,10 +1240,8 @@ if [ $1 -gt 1 ] ; then test -f '/var/lib/ipa-client/sysrestore/sysrestore.index' && restore=$(wc -l '/var/lib/ipa-client/sysrestore/sysrestore.index' | awk '{print $1}') if [ -f '/etc/sssd/sssd.conf' -a $restore -ge 2 ]; then - if ! grep -E -q '/var/lib/sss/pubconf/krb5.include.d/' /etc/krb5.conf 2>/dev/null ; then - echo "includedir /var/lib/sss/pubconf/krb5.include.d/" > /etc/krb5.conf.ipanew - cat /etc/krb5.conf >> /etc/krb5.conf.ipanew - mv -Z /etc/krb5.conf.ipanew /etc/krb5.conf + if grep -E -q '/var/lib/sss/pubconf/krb5.include.d/' /etc/krb5.conf 2>/dev/null ; then + sed -i '\;includedir /var/lib/sss/pubconf/krb5.include.d;d' /etc/krb5.conf fi fi @@ -1715,21 +1736,59 @@ fi %endif %changelog -* Fri Feb 10 2023 Rafael Jeffman - 4.9.11-5 -- Wipe the ipa-ca DNS record when updating system records - Resolves: RHBZ#2158775 +* Thu Aug 31 2023 Rafael Jeffman - 4.9.12-8 +- Require krb5 release 1.18.2-25 or later + Resolves: RHBZ#2234711 -* Thu Feb 09 2023 Rafael Jeffman - 4.9.11-4 -- trust-add: handle missinf msSFU30MaxGidNumber - Resolves: RHBZ#2162355 -- Backport latest test fixes for python3-ipatests - Resolves: RHBZ#2166929 -- server install: remove error log about missing bkup file - Resolves: RHBZ#2160389 -- automember-rebuild: add a notice about high CPU usage - Resolves: RHBZ#2018198 -- ipa-kdb: PAC consistency checker needs to handle child domains as well - Resolves: RHBZ#2166324 +* Wed Aug 16 2023 Rafael Jeffman - 4.9.12-7 +- ipatests: fix test_topology + Resolves: RHBZ#2232351 +- Installer: activate nss and pam services in sssd.conf + Resolves: RHBZ#2216532 + +* Thu Aug 10 2023 Rafael Jeffman - 4.9.12-6 +- ipa-kdb: fix error handling of is_master_host() + Resolves: RHBZ#2214638 +- ipatests: enable firewall rule for http service on acme client + Resolves: RHBZ#2230256 +- User plugin: improve error related to non existing idp + Resolves: RHBZ#2224572 +- Prevent admin user from being deleted + Resolves: RHBZ#1821181 +- Fix memory leak in the OTP last token plugin + Resolves: RHBZ#2227783 + +* Mon Jul 17 2023 Rafael Jeffman - 4.9.12-5 +- Upgrade: fix replica agreement, fix backported patch + Related: RHBZ#2216551 + +* Fri Jun 30 2023 Rafael Jeffman - 4.9.12-4 +- kdb: Use-krb5_pac_full_sign_compat() when available + Resolves: RHBZ#2176406 +- OTP: fix-data-type-to-avoid-endianness-issue + Resolves: RHBZ#2218293 +- Upgrade: fix replica agreement + Resolves: RHBZ#2216551 +- Upgrade: add PKI drop-in file if missing + Resolves: RHBZ#2215336 +- Use the python-cryptography parser directly in cert-find + Resolves: RHBZ#2164349 +- Backport test updates + Resolves: RHBZ#221884 + +* Wed Jun 21 2023 Julien Rische - 4.9.12-3 +- Rely on sssd-krb5 to include SSSD-generated krb5 configuration + Resolves: RHBZ#2214563 + +* Thu May 25 2023 Rafael Jeffman - 4.9.12-2 +- Use the OpenSSL certificate parser in cert-find + Resolves: RHBZ#2209947 + +* Wed May 24 2023 Rafael Jeffman - 4.9.12-1 +- Rebase ipa to 4.9.12 + Resolves: RHBZ#2196425 +- user or group name: explain the supported format + Resolves: RHBZ#2150217 * Mon Dec 19 2022 Rafael Jeffman - 4.9.11-3 - Revert DNSResolver Fix use of nameservers with ports.