Compare commits

...

4 Commits

Author SHA1 Message Date
6658167768 Import from CS git 2025-10-02 11:38:27 +00:00
669dd08371 Import from CS git 2025-06-23 10:08:09 +00:00
958adc2193 Import from CS git 2025-04-22 08:07:52 +00:00
f79c669f55 Import from CS git 2024-12-17 08:57:26 +00:00
14 changed files with 2976 additions and 24 deletions

View File

@ -40,12 +40,11 @@ index 06d511c76..dbb98dba6 100644
#include "ipa_krb5.h"
#include "ipa_hostname.h"
+#include <kadm5/admin.h>
#define IPADB_GLOBAL_CONFIG_CACHE_TIME 60
@@ -207,6 +208,19 @@ static const struct {
@@ -207,5 +208,18 @@ static const struct {
{ "idp", IPADB_USER_AUTH_IDP },
{ "passkey", IPADB_USER_AUTH_PASSKEY },
{ }
+},
+ objclass_table[] = {
@ -61,10 +60,10 @@ index 06d511c76..dbb98dba6 100644
+ { KADM5_HIST_PRINCIPAL, IPADB_USER_AUTH_PASSWORD },
+ { }
};
void ipadb_parse_user_auth(LDAP *lcontext, LDAPMessage *le,
@@ -217,17 +231,49 @@ void ipadb_parse_user_auth(LDAP *lcontext, LDAPMessage *le,
*userauth = IPADB_USER_AUTH_NONE;
vals = ldap_get_values_len(lcontext, le, IPA_USER_AUTH_TYPE);
- if (!vals)
@ -121,7 +120,7 @@ index 06d511c76..dbb98dba6 100644
/* If password auth is enabled, enable hardened policy too. */
if (*userauth & IPADB_USER_AUTH_PASSWORD) {
*userauth |= IPADB_USER_AUTH_HARDENED;
--
--
2.43.0
@ -163,7 +162,7 @@ index 436ee0e62..2802221c7 100644
pol_limits = &(ied->pol_limits[IPADB_USER_AUTH_IDX_PKINIT]);
} else if (strcmp(auth_indicator, "hardened") == 0) {
valid_auth_indicators++;
--
--
2.43.0
@ -188,14 +187,14 @@ index dbb98dba6..4e6cacf24 100644
@@ -195,6 +195,9 @@ done:
return base;
}
+/* In this table all _AUTH_PASSWORD entries will be
+ * expanded to include _AUTH_HARDENED in ipadb_parse_user_auth()
+ * which means there is no need to explicitly add it here */
static const struct {
const char *name;
enum ipadb_user_auth flag;
--
--
2.43.0
@ -230,7 +229,7 @@ index caa0e6a34..5c2e7af02 100644
@@ -23,6 +23,24 @@ class TestPkinitClientInstall(IntegrationTest):
def install(cls, mh):
tasks.install_master(cls.master)
+ def enforce_password_and_otp(self):
+ """enforce otp by default and password for admin """
+ self.master.run_command(
@ -255,7 +254,7 @@ index caa0e6a34..5c2e7af02 100644
@@ -86,6 +104,14 @@ class TestPkinitClientInstall(IntegrationTest):
cabundle = self.master.get_file_contents(paths.KDC_CA_BUNDLE_PEM)
client.put_file_contents(self.tmpbundle, cabundle)
+ def test_restart_krb5kdc(self):
+ tasks.kinit_admin(self.master)
+ self.enforce_password_and_otp()
@ -267,6 +266,6 @@ index caa0e6a34..5c2e7af02 100644
def test_client_install_pkinit(self):
tasks.kinit_admin(self.master)
self.add_certmaperule()
--
--
2.43.0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,87 @@
diff --git a/install/updates/50-krbenctypes.update b/install/updates/50-krbenctypes.update
index 1058a92..1bf2bf3 100644
--- a/install/updates/50-krbenctypes.update
+++ b/install/updates/50-krbenctypes.update
@@ -7,3 +7,5 @@ add: krbSupportedEncSaltTypes: aes128-sha2:normal
add: krbSupportedEncSaltTypes: aes128-sha2:special
add: krbSupportedEncSaltTypes: aes256-sha2:normal
add: krbSupportedEncSaltTypes: aes256-sha2:special
+remove: krbDefaultEncSaltTypes: des3-hmac-sha1:special
+remove: krbDefaultEncSaltTypes: arcfour-hmac:special
diff --git a/install/updates/60-trusts.update b/install/updates/60-trusts.update
index 56e3920..b2fdcca 100644
--- a/install/updates/60-trusts.update
+++ b/install/updates/60-trusts.update
@@ -54,4 +54,4 @@ add:aci: (target="ldap:///krbprincipalname=cifs/($$dn),cn=services,cn=accounts,$
# Add the default PAC type to configuration
dn: cn=ipaConfig,cn=etc,$SUFFIX
-addifnew: ipaKrbAuthzData: MS-PAC
+add: ipaKrbAuthzData: MS-PAC
diff --git a/ipatests/test_integration/test_installation.py b/ipatests/test_integration/test_installation.py
index d41c1ee..ef0727e 100644
--- a/ipatests/test_integration/test_installation.py
+++ b/ipatests/test_integration/test_installation.py
@@ -1188,6 +1188,21 @@ class TestInstallMaster(IntegrationTest):
expected_stdout=f'href="https://{self.master.hostname}/'
)
+ def test_pac_configuration_enabled(self):
+ """
+ This testcase checks that the default PAC type
+ is added to configuration.
+ """
+ base_dn = str(self.master.domain.basedn)
+ dn = DN(
+ ("cn", "ipaConfig"),
+ ("cn", "etc"),
+ base_dn
+ )
+ result = tasks.ldapsearch_dm(self.master, str(dn),
+ ["ipaKrbAuthzData"])
+ assert 'ipaKrbAuthzData: MS-PAC' in result.stdout_text
+
def test_hostname_parameter(self, server_cleanup):
"""
Test that --hostname parameter is respected in interactive mode.
diff --git a/ipatests/test_integration/test_upgrade.py b/ipatests/test_integration/test_upgrade.py
index 182e3b5..8465cf9 100644
--- a/ipatests/test_integration/test_upgrade.py
+++ b/ipatests/test_integration/test_upgrade.py
@@ -165,7 +165,6 @@ class TestUpgrade(IntegrationTest):
ldap.update_entry(location_krb_rec)
yield _setup_locations
-
ldap = self.master.ldap_connect()
modified = False
@@ -477,3 +476,28 @@ class TestUpgrade(IntegrationTest):
self.master.run_command(['ipa-server-upgrade'])
assert self.master.transport.file_exists(
paths.SYSTEMD_PKI_TOMCAT_IPA_CONF)
+
+ def test_mspac_attribute_set(self):
+ """
+ This testcase deletes the already existing attribute
+ 'ipaKrbAuthzData: MS-PAC'.
+ The test then runs ipa-server-upgrade and checks that
+ the attribute 'ipaKrbAuthzData: MS-PAC' is added again.
+ """
+ base_dn = str(self.master.domain.basedn)
+ dn = DN(
+ ("cn", "ipaConfig"),
+ ("cn", "etc"),
+ base_dn
+ )
+ ldif = textwrap.dedent("""
+ dn: cn=ipaConfig,cn=etc,{}
+ changetype: modify
+ delete: ipaKrbAuthzData
+ """).format(base_dn)
+ tasks.ldapmodify_dm(self.master, ldif)
+ tasks.kinit_admin(self.master)
+ self.master.run_command(['ipa-server-upgrade'])
+ result = tasks.ldapsearch_dm(self.master, str(dn),
+ ["ipaKrbAuthzData"])
+ assert 'ipaKrbAuthzData: MS-PAC' in result.stdout_text

View File

@ -0,0 +1,72 @@
From f6645ebe5c0c0c030ec2e62e007d8dacd1b4e4cf Mon Sep 17 00:00:00 2001
From: Erik Belko <ebelko@redhat.com>
Date: Sep 03 2024 12:54:30 +0000
Subject: ipatests: Update ipa-adtrust-install test
update test_user_connects_smb_share_if_locked_specific_group with wait
for SSSD to be online after ipa-adtrust-install command
Related: https://pagure.io/freeipa/issue/9655
Signed-off-by: Erik Belko <ebelko@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
---
diff --git a/ipatests/test_integration/test_adtrust_install.py b/ipatests/test_integration/test_adtrust_install.py
index 72e8d87..de252db 100644
--- a/ipatests/test_integration/test_adtrust_install.py
+++ b/ipatests/test_integration/test_adtrust_install.py
@@ -853,6 +853,8 @@ class TestIpaAdTrustInstall(IntegrationTest):
self.master.config.admin_password,
"-U"]
)
+ # Wait for SSSD to become online before doing any other check
+ tasks.wait_for_sssd_domain_status_online(self.master)
self.master.run_command(["mkdir", "/freeipa4234"])
self.master.run_command(
["chcon", "-t", "samba_share_t",
From 47920e78c81380c0a40986e55f05246aac132fbb Mon Sep 17 00:00:00 2001
From: Erik Belko <ebelko@redhat.com>
Date: May 21 2024 12:50:46 +0000
Subject: ipatests: Update ipa-adtrust-install test
update after change in implementation of `krb_utils.get_principal()` now using GSSAPI
Related: https://pagure.io/freeipa/issue/9575
Signed-off-by: Erik Belko <ebelko@redhat.com>
Reviewed-By: Michal Polovka <mpolovka@redhat.com>
---
diff --git a/ipatests/test_integration/test_adtrust_install.py b/ipatests/test_integration/test_adtrust_install.py
index 86d8d20..72e8d87 100644
--- a/ipatests/test_integration/test_adtrust_install.py
+++ b/ipatests/test_integration/test_adtrust_install.py
@@ -464,18 +464,15 @@ class TestIpaAdTrustInstall(IntegrationTest):
password
"""
password = "wrong_pwd"
- msg = (
- "Must have Kerberos credentials to setup AD trusts on server: "
- "Major (458752): No credentials were supplied, or the credentials "
- "were unavailable or inaccessible, Minor (2529639053): "
- "No Kerberos credentials available (default cache: KCM:)\n"
+ expected_substring = (
+ "Must have Kerberos credentials to setup AD trusts on server:"
)
self.master.run_command(["kdestroy", "-A"])
result = self.master.run_command(
["ipa-adtrust-install", "-A", "admin", "-a",
password, "-U"], raiseonerr=False
)
- assert msg in result.stderr_text
+ assert expected_substring in result.stderr_text
assert result.returncode != 0
def test_adtrust_install_with_invalid_rid_base_value(self):

View File

@ -0,0 +1,245 @@
From 19f22cf75ae768dd2b6c0d674cf55f8d6ffafb31 Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Mar 07 2025 06:48:02 +0000
Subject: Replica CA installation: ignore time skew during initial replication
During a replica CA installation, the initial replication step may fail
if there is too much time skew between the server and replica.
The replica installer already takes care of this for the replication of
the domain suffix but the replica CA installer does not set
nssldapd-ignore-time-skew to on for o=ipaca suffix.
During a replica CA installation, read the initial value of
nssldapd-ignore-time-skew, force it to on, start replication and
revert to the initial value.
Apply the same logic to dsinstance and ipa-replica-manage force-sync.
Fixes: https://pagure.io/freeipa/issue/9635
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
diff --git a/install/share/Makefile.am b/install/share/Makefile.am
index e0fe4b7..4029297 100644
--- a/install/share/Makefile.am
+++ b/install/share/Makefile.am
@@ -38,7 +38,6 @@ dist_app_DATA = \
default-trust-view.ldif \
delegation.ldif \
replica-acis.ldif \
- replica-prevent-time-skew.ldif \
ds-nfiles.ldif \
ds-ipa-env.conf.template \
dns.ldif \
diff --git a/install/share/replica-prevent-time-skew.ldif b/install/share/replica-prevent-time-skew.ldif
deleted file mode 100644
index 5d301fe..0000000
--- a/install/share/replica-prevent-time-skew.ldif
+++ /dev/null
@@ -1,4 +0,0 @@
-dn: cn=config
-changetype: modify
-replace: nsslapd-ignore-time-skew
-nsslapd-ignore-time-skew: $SKEWVALUE
diff --git a/install/tools/ipa-replica-manage.in b/install/tools/ipa-replica-manage.in
index cebf73a..71851be 100644
--- a/install/tools/ipa-replica-manage.in
+++ b/install/tools/ipa-replica-manage.in
@@ -1237,12 +1237,13 @@ def force_sync(realm, thishost, fromhost, dirman_passwd, nolookup=False):
repl.force_sync(repl.conn, fromhost)
else:
ds = dsinstance.DsInstance(realm_name=realm)
- ds.replica_manage_time_skew(prevent=False)
+ ds.replica_ignore_initial_time_skew()
repl = replication.ReplicationManager(realm, fromhost, dirman_passwd)
repl.force_sync(repl.conn, thishost)
agreement = repl.get_replication_agreement(thishost)
repl.wait_for_repl_update(repl.conn, agreement.dn)
- ds.replica_manage_time_skew(prevent=True)
+ ds.replica_revert_time_skew()
+
def show_DNA_ranges(hostname, master, realm, dirman_passwd, nextrange=False,
nolookup=False):
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index 35cec89..e15e629 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -409,7 +409,11 @@ class CAInstance(DogtagInstance):
if promote:
# Setup Database
self.step("creating certificate server db", self.__create_ds_db)
+ self.step("ignore time skew for initial replication",
+ self.replica_ignore_initial_time_skew)
self.step("setting up initial replication", self.__setup_replication)
+ self.step("revert time skew after initial replication",
+ self.replica_revert_time_skew)
self.step("creating ACIs for admin", self.add_ipaca_aci)
self.step("creating installation admin user", self.setup_admin)
self.step("configuring certificate server instance",
diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
index cbacfae..ba4bf8a 100644
--- a/ipaserver/install/dsinstance.py
+++ b/ipaserver/install/dsinstance.py
@@ -385,11 +385,11 @@ class DsInstance(service.Service):
# This helps with initial replication or force-sync because
# the receiving side has no valuable changes itself yet.
self.step("ignore time skew for initial replication",
- self.__replica_ignore_initial_time_skew)
+ self.replica_ignore_initial_time_skew)
self.step("setting up initial replication", self.__setup_replica)
self.step("prevent time skew after initial replication",
- self.replica_manage_time_skew)
+ self.replica_revert_time_skew)
self.step("adding sasl mappings to the directory", self.__configure_sasl_mappings)
self.step("updating schema", self.__update_schema)
# See LDIFs for automember configuration during replica install
@@ -995,16 +995,6 @@ class DsInstance(service.Service):
def __add_replication_acis(self):
self._ldap_mod("replica-acis.ldif", self.sub_dict)
- def __replica_ignore_initial_time_skew(self):
- self.replica_manage_time_skew(prevent=False)
-
- def replica_manage_time_skew(self, prevent=True):
- if prevent:
- self.sub_dict['SKEWVALUE'] = 'off'
- else:
- self.sub_dict['SKEWVALUE'] = 'on'
- self._ldap_mod("replica-prevent-time-skew.ldif", self.sub_dict)
-
def __setup_s4u2proxy(self):
def __add_principal(last_cn, principal, self):
diff --git a/ipaserver/install/service.py b/ipaserver/install/service.py
index 13ae346..15ca70b 100644
--- a/ipaserver/install/service.py
+++ b/ipaserver/install/service.py
@@ -811,6 +811,31 @@ class Service:
self.run_getkeytab(self.api.env.ldap_uri, self.keytab, self.principal)
self.set_keytab_owner()
+ def replica_ignore_initial_time_skew(self):
+ """
+ Set nsslapd-ignore-time-skew = on if not already set
+ and store the initial value in order to restore it later.
+
+ The on value allows replica initialization even if there
+ are excessive time skews.
+ """
+ dn = DN(('cn', 'config'))
+ entry_attrs = api.Backend.ldap2.get_entry(dn)
+ self.original_time_skew = entry_attrs['nsslapd-ignore-time-skew'][0]
+ if self.original_time_skew != 'on':
+ entry_attrs['nsslapd-ignore-time-skew'] = 'on'
+ api.Backend.ldap2.update_entry(entry_attrs)
+
+ def replica_revert_time_skew(self):
+ """
+ Revert nsslapd-ignore-time-skew to its previous value.
+ """
+ dn = DN(('cn', 'config'))
+ entry_attrs = api.Backend.ldap2.get_entry(dn)
+ if self.original_time_skew != 'on':
+ entry_attrs['nsslapd-ignore-time-skew'] = self.original_time_skew
+ api.Backend.ldap2.update_entry(entry_attrs)
+
class SimpleServiceInstance(Service):
def create_instance(self, gensvc_name=None, fqdn=None, ldap_suffix=None,
From a6bb2fa4997dd7894dbf75d1c3fd1deaebd3e05c Mon Sep 17 00:00:00 2001
From: Sudhir Menon <sumenon@redhat.com>
Date: Mar 07 2025 06:48:02 +0000
Subject: ipatests: Test to check that the configured value for "nsslapd-ignore-time-skew" remains on even after a "force-sync" is done
Related: https://pagure.io/freeipa/issue/9635
Signed-off-by: Sudhir Menon <sumenon@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
---
diff --git a/ipatests/test_integration/test_installation.py b/ipatests/test_integration/test_installation.py
index ef0727e..3673f7f 100644
--- a/ipatests/test_integration/test_installation.py
+++ b/ipatests/test_integration/test_installation.py
@@ -2132,3 +2132,69 @@ class TestHostnameValidator(IntegrationTest):
assert result.returncode == 1
assert 'hostname cannot be the same as the domain name' \
in result.stderr_text
+
+
+class TestNsslapdIgnoreTimeSkew(IntegrationTest):
+ """
+ Test to check nsslapd-ignore-time-skew is not disabled.
+ """
+ num_replicas = 1
+ topology = 'line'
+
+ @pytest.fixture
+ def update_time_skew(self):
+ """
+ Fixture enables nsslapd-ignore-time-skew
+ parameter and reverts it back
+ """
+ ldap = self.replicas[0].ldap_connect()
+ dn = DN(
+ ("cn", "config"),
+ )
+ entry = ldap.get_entry(dn)
+ entry.single_value["nsslapd-ignore-time-skew"] = 'on'
+ ldap.update_entry(entry)
+
+ yield
+
+ entry = ldap.get_entry(dn)
+ entry.single_value["nsslapd-ignore-time-skew"] = 'off'
+ ldap.update_entry(entry)
+
+ def test_check_nsslapd_ignore_time_skew(self):
+ """
+ This testcase checks that the ignore time skew parameter
+ is set to on during the directory server replica
+ installation (replication of the suffix) and during
+ the CA replica (replication of o=ipaca).
+ It also checks that the time skew is reverted during
+ pki_tomcat setup stage.
+ """
+ DIRSRV_LOG = (
+ "ignore time skew for initial replication"
+ )
+ PKI_TOMCAT_LOG = (
+ "revert time skew after initial replication"
+ )
+ install_msg = self.replicas[0].get_file_contents(
+ paths.IPAREPLICA_INSTALL_LOG, encoding="utf-8"
+ )
+ dirsrv_msg = re.findall(DIRSRV_LOG, install_msg)
+ assert len(dirsrv_msg) == 2
+ assert PKI_TOMCAT_LOG in install_msg
+
+ def test_forcesync_does_not_overwrite_ignore_time_skew(
+ self, update_time_skew):
+ """
+ This testcase checks that calling ipa-replica-manage
+ force-sync does not overwrite the value of ignore
+ time skew
+ """
+ result = self.replicas[0].run_command(
+ ["ipa-replica-manage", "force-sync",
+ "--from", self.master.hostname,
+ "--no-lookup", "-v"])
+ assert result.returncode == 0
+ conn = self.replicas[0].ldap_connect()
+ ldap_entry = conn.get_entry(DN("cn=config"))
+ assert ldap_entry.single_value['nsslapd-ignore-time-skew'] == "on"

View File

@ -0,0 +1,82 @@
From ac6eee670d8a753e66ba69a65eff55447fff2822 Mon Sep 17 00:00:00 2001
From: Aleksandr Sharov <asharov@redhat.com>
Date: Mar 25 2025 09:33:06 +0000
Subject: Add a check into ipa-cert-fix tool to avoid updating certs if CA is close to being expired.
Fixes: https://pagure.io/freeipa/issue/9760
Signed-off-by: Aleksandr Sharov <asharov@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
---
diff --git a/ipaserver/install/ipa_cert_fix.py b/ipaserver/install/ipa_cert_fix.py
index 8e02d1e..960d7b9 100644
--- a/ipaserver/install/ipa_cert_fix.py
+++ b/ipaserver/install/ipa_cert_fix.py
@@ -69,6 +69,7 @@ logger = logging.getLogger(__name__)
cert_nicknames = {
+ 'ca_issuing': 'caSigningCert cert-pki-ca',
'sslserver': 'Server-Cert cert-pki-ca',
'subsystem': 'subsystemCert cert-pki-ca',
'ca_ocsp_signing': 'ocspSigningCert cert-pki-ca',
@@ -137,6 +138,16 @@ class IPACertFix(AdminTool):
print("Nothing to do.")
return 0
+ if any(key == 'ca_issuing' for key, _ in certs):
+ logger.debug("CA signing cert is expired, exiting!")
+ print(
+ "The CA signing certificate is expired or will expire within "
+ "the next two weeks.\n\nipa-cert-fix cannot proceed, please "
+ "refer to the ipa-cacert-manage tool to renew the CA "
+ "certificate before proceeding."
+ )
+ return 1
+
print(msg)
print_intentions(certs, extra_certs, non_renewed)
From cdc03d7b6233f736c51c10aa07225aac9715e4c0 Mon Sep 17 00:00:00 2001
From: Aleksandr Sharov <asharov@redhat.com>
Date: Mar 25 2025 18:03:54 +0000
Subject: Test fix for the update
Fixes: https://pagure.io/freeipa/issue/9760
Signed-off-by: Aleksandr Sharov <asharov@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
---
diff --git a/ipatests/test_integration/test_ipa_cert_fix.py b/ipatests/test_integration/test_ipa_cert_fix.py
index 15d8a81..d11fd3d 100644
--- a/ipatests/test_integration/test_ipa_cert_fix.py
+++ b/ipatests/test_integration/test_ipa_cert_fix.py
@@ -301,13 +301,18 @@ class TestIpaCertFix(IntegrationTest):
valid. If CA cert expired, ipa-cert-fix won't work.
related: https://pagure.io/freeipa/issue/8721
+
+ If CA cert is close to expiry, there's no reason to issue new certs
+ with short validity period. So, ipa-cert-fix should fail in this case.
+
+ related: https://pagure.io/freeipa/issue/9760
"""
result = self.master.run_command(['ipa-cert-fix', '-v'],
stdin_text='yes\n',
raiseonerr=False)
# check that pki-server cert-fix command fails
- err_msg = ("ERROR: CalledProcessError(Command "
- "['pki-server', 'cert-fix'")
+ err_msg = ("CA signing cert is expired, exiting!")
+ assert result.returncode == 1
assert err_msg in result.stderr_text

View File

@ -0,0 +1,84 @@
From ae37b3e6ed12bddb650bdce8e9729e81fef40840 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: May 08 2025 06:21:00 +0000
Subject: kdb: keep ipadb_get_connection() from succeeding with null LDAP context
The final call to ipadb_reinit_mspac() in ipadb_get_connection() is not
considered essential for the function to succeed, as there might be
cases where the required pieces of information to generate PACs are not
yet configured in the database. However, in environments where 389ds is
overwhelmed, the LDAP connection established at the beginning of
ipadb_get_connection() might already be lost while executing
ipadb_reinit_mspac().
Connection errors were not distinguished from configuration errors,
which could result in ipadb_get_connection() succeeding while the LDAP
context is set to null, leading to a KDC crash on the next LDAP request.
ipadb_get_connection() now explicitly checks the value of the LDAP
context before returning.
Fixes: https://pagure.io/freeipa/issue/9777
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Rafael Guterres Jeffman <rjeffman@redhat.com>
---
diff --git a/daemons/ipa-kdb/ipa_kdb.c b/daemons/ipa-kdb/ipa_kdb.c
index fcadb8e..98315a0 100644
--- a/daemons/ipa-kdb/ipa_kdb.c
+++ b/daemons/ipa-kdb/ipa_kdb.c
@@ -524,26 +524,43 @@ int ipadb_get_connection(struct ipadb_context *ipactx)
/* get adtrust options using default refresh interval */
ret = ipadb_reinit_mspac(ipactx, false, &stmsg);
- if (ret && stmsg)
- krb5_klog_syslog(LOG_WARNING, "MS-PAC generator: %s", stmsg);
+ if (ret) {
+ if (stmsg) {
+ krb5_klog_syslog(LOG_WARNING, "MS-PAC generator: %s", stmsg);
+ }
+ /* Initialization of the MS-PAC generator is an optional dependency.
+ * Fail only if the connection was lost. */
+ if (!ipactx->lcontext) {
+ goto done;
+ }
+ }
ret = 0;
done:
ldap_msgfree(res);
+ /* LDAP context should never be null on success, but keep this test out of
+ * security to make sure we do not return an invalid context. */
+ if (ret == 0 && !ipactx->lcontext) {
+ krb5_klog_syslog(LOG_WARNING, "Internal malfunction: LDAP connection "
+ "process resulted in an invalid context "
+ "(please report this incident)");
+ ret = LDAP_SERVER_DOWN;
+ }
+
if (ret) {
+ /* Cleanup LDAP context if connection failed. */
if (ipactx->lcontext) {
ldap_unbind_ext_s(ipactx->lcontext, NULL, NULL);
ipactx->lcontext = NULL;
}
- if (ret == LDAP_SERVER_DOWN) {
- return ETIMEDOUT;
- }
- return EIO;
+
+ /* Replace LDAP error code by POSIX error code. */
+ ret = ret == LDAP_SERVER_DOWN ? ETIMEDOUT : EIO;
}
- return 0;
+ return ret;
}
static krb5_principal ipadb_create_local_tgs(krb5_context kcontext,

View File

@ -0,0 +1,189 @@
From d6d2282f9f1b93ae7fb6e074920e41e64f35ab12 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Mon, 28 Apr 2025 13:43:40 -0400
Subject: [PATCH] Set krbCanonicalName=admin@REALM on the admin user
The admin must always own this name. If another entry has this
value set then remove it.
There is a uniqueness plugin for this attribute so the only two
possibilities are:
- no entry has this value set
- the admin user has this value set
- a different entry has the value set
Still, for robustness purposes, the upgrade plugin will handle
more entries.
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
---
install/share/bootstrap-template.ldif | 1 +
.../updates/90-post_upgrade_plugins.update | 1 +
.../plugins/add_admin_krbcanonicalname.py | 79 +++++++++++++++++++
ipatests/test_integration/test_commands.py | 38 +++++++++
4 files changed, 119 insertions(+)
create mode 100644 ipaserver/install/plugins/add_admin_krbcanonicalname.py
diff --git a/install/share/bootstrap-template.ldif b/install/share/bootstrap-template.ldif
index 325eb8450..94972eb72 100644
--- a/install/share/bootstrap-template.ldif
+++ b/install/share/bootstrap-template.ldif
@@ -239,6 +239,7 @@ objectClass: ipasshuser
uid: admin
krbPrincipalName: admin@$REALM
krbPrincipalName: root@$REALM
+krbCanonicalName: admin@$REALM
cn: Administrator
sn: Administrator
uidNumber: $IDSTART
diff --git a/install/updates/90-post_upgrade_plugins.update b/install/updates/90-post_upgrade_plugins.update
index 7c3bba3e0..3d78c7b5a 100644
--- a/install/updates/90-post_upgrade_plugins.update
+++ b/install/updates/90-post_upgrade_plugins.update
@@ -25,6 +25,7 @@ plugin: update_mapping_Guests_to_nobody
plugin: fix_kra_people_entry
plugin: update_pwpolicy
plugin: update_pwpolicy_grace
+plugin: add_admin_krbcanonicalname
# last
# DNS version 1
diff --git a/ipaserver/install/plugins/add_admin_krbcanonicalname.py b/ipaserver/install/plugins/add_admin_krbcanonicalname.py
new file mode 100644
index 000000000..e9ffdf55a
--- /dev/null
+++ b/ipaserver/install/plugins/add_admin_krbcanonicalname.py
@@ -0,0 +1,79 @@
+#
+# Copyright (C) 2025 FreeIPA Contributors see COPYING for license
+#
+
+from __future__ import absolute_import
+
+import logging
+
+from ipalib import errors
+from ipalib import Registry
+from ipalib import Updater
+from ipapython.dn import DN
+
+logger = logging.getLogger(__name__)
+
+register = Registry()
+
+
+@register()
+class add_admin_krbcanonicalname(Updater):
+ """
+ Ensures that only the admin user has the krbCanonicalName of
+ admin@$REALM.
+ """
+
+ def execute(self, **options):
+ ldap = self.api.Backend.ldap2
+
+ search_filter = (
+ "(krbcanonicalname=admin@{})".format(self.api.env.realm))
+ try:
+ (entries, _truncated) = ldap.find_entries(
+ filter=search_filter, base_dn=self.api.env.basedn,
+ time_limit=0, size_limit=0)
+ except errors.EmptyResult:
+ logger.debug("add_admin_krbcanonicalname: No user set with "
+ "admin krbcanonicalname")
+ entries = []
+ # fall through
+ except errors.ExecutionError as e:
+ logger.error("add_admin_krbcanonicalname: Can not get list "
+ "of krbcanonicalname: %s", e)
+ return False, []
+
+ admin_set = False
+ # admin should be only user with admin@ as krbcanonicalname
+ # It has a uniquness setting so there can be only one, we
+ # just didn't automatically set it for admin.
+ for entry in entries:
+ if entry.single_value.get('uid') != 'admin':
+ logger.critical(
+ "add_admin_krbcanonicalname: "
+ "entry %s has a krbcanonicalname of admin. Removing.",
+ entry.dn)
+ del entry['krbcanonicalname']
+ ldap.update_entry(entry)
+ else:
+ admin_set = True
+
+ if not admin_set:
+ dn = DN(
+ ('uid', 'admin'),
+ self.api.env.container_user,
+ self.api.env.basedn)
+ entry = ldap.get_entry(dn)
+ entry['krbcanonicalname'] = 'admin@%s' % self.api.env.realm
+ try:
+ ldap.update_entry(entry)
+ except errors.DuplicateEntry:
+ logger.critical(
+ "add_admin_krbcanonicalname: "
+ "Failed to set krbcanonicalname on admin. It is set "
+ "on another entry.")
+ except errors.ExecutionError as e:
+ logger.critical(
+ "add_admin_krbcanonicalname: "
+ "Failed to set krbcanonicalname on admin: %s", e)
+
+ return False, []
diff --git a/ipatests/test_integration/test_commands.py b/ipatests/test_integration/test_commands.py
index 621982c4f..1526a6e0d 100644
--- a/ipatests/test_integration/test_commands.py
+++ b/ipatests/test_integration/test_commands.py
@@ -1796,6 +1796,44 @@ class TestIPACommandWithoutReplica(IntegrationTest):
assert result.returncode == 1
assert 'cannot be deleted or disabled' in result.stderr_text
+ def test_unique_krbcanonicalname(self):
+ """Verify that the uniqueness for krbcanonicalname is working"""
+ master = self.master
+
+ base_dn = str(master.domain.basedn)
+ hostname = master.hostname
+ realm = master.domain.realm
+ principal = f'test/{hostname}@{realm}'
+ entry_ldif = textwrap.dedent("""
+ dn: krbprincipalname={principal},cn=services,cn=accounts,{base_dn}
+ changetype: add
+ ipakrbprincipalalias: test/{hostname}@{realm}
+ krbprincipalname: {principal}
+ objectclass: ipakrbprincipal
+ objectclass: ipaobject
+ objectclass: ipaservice
+ objectclass: krbprincipal
+ objectclass: krbprincipalaux
+ objectclass: top
+ krbcanonicalname: admin@{realm}
+ managedby: fqdn={hostname},cn=computers,cn=accounts,{base_dn}
+ """).format(
+ base_dn=base_dn,
+ hostname=hostname,
+ principal=principal,
+ realm=realm)
+ tasks.kdestroy_all(master)
+ master.run_command(
+ ['kinit', '-kt', '/etc/krb5.keytab', f'host/{hostname}@{realm}'])
+ args = [
+ 'ldapmodify',
+ '-Y',
+ 'GSSAPI'
+ ]
+ result = master.run_command(args, stdin_text=entry_ldif,
+ raiseonerr=False)
+ assert "entry with the same attribute value" in result.stderr_text
+
class TestIPACommandWithoutReplica(IntegrationTest):
"""
--
2.48.1

View File

@ -0,0 +1,106 @@
From a37de8c22976a75caf969e232229ff6521ff4936 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcritten@redhat.com>
Date: Thu, 10 Jul 2025 11:44:36 -0400
Subject: [PATCH] Enforce uniqueness across krbprincipalname and
krbcanonicalname
This relies on a fix in 389-ds that extends the uniqueness plugin
to be able to compare attributes with different matching syntax.
This will prevent privilege escalation attacks if one of the
attributes is not set on an entry if it is set elsewhere.
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
---
install/share/unique-attributes.ldif | 28 +++++-----------------------
install/updates/10-uniqueness.update | 27 +++++++++++++++++++++++----
2 files changed, 28 insertions(+), 27 deletions(-)
diff --git a/install/share/unique-attributes.ldif b/install/share/unique-attributes.ldif
index 60f2c3470..b28d981b5 100644
--- a/install/share/unique-attributes.ldif
+++ b/install/share/unique-attributes.ldif
@@ -1,34 +1,16 @@
-dn: cn=krbPrincipalName uniqueness,cn=plugins,cn=config
+dn: cn=kerberos name uniqueness,cn=plugins,cn=config
changetype: add
objectClass: top
objectClass: nsSlapdPlugin
objectClass: extensibleObject
-cn: krbPrincipalName uniqueness
+cn: kerberos name uniqueness
nsslapd-pluginPath: libattr-unique-plugin
nsslapd-pluginInitfunc: NSUniqueAttr_Init
nsslapd-pluginType: preoperation
nsslapd-pluginEnabled: on
-uniqueness-attribute-name: krbPrincipalName
-nsslapd-plugin-depends-on-type: database
-nsslapd-pluginId: NSUniqueAttr
-nsslapd-pluginVersion: 1.1.0
-nsslapd-pluginVendor: Fedora Project
-nsslapd-pluginDescription: Enforce unique attribute values
-uniqueness-subtrees: $SUFFIX
-uniqueness-exclude-subtrees: cn=staged users,cn=accounts,cn=provisioning,$SUFFIX
-uniqueness-across-all-subtrees: on
-
-dn: cn=krbCanonicalName uniqueness,cn=plugins,cn=config
-changetype: add
-objectClass: top
-objectClass: nsSlapdPlugin
-objectClass: extensibleObject
-cn: krbCanonicalName uniqueness
-nsslapd-pluginPath: libattr-unique-plugin
-nsslapd-pluginInitfunc: NSUniqueAttr_Init
-nsslapd-pluginType: preoperation
-nsslapd-pluginEnabled: on
-uniqueness-attribute-name: krbCanonicalName
+uniqueness-attribute-name: krbPrincipalName:CaseIgnoreMatch:
+uniqueness-attribute-name: krbPrincipalAlias:CaseIgnoreMatch:
+uniqueness-attribute-name: krbCanonicalName:CaseIgnoreMatch:
nsslapd-plugin-depends-on-type: database
nsslapd-pluginId: NSUniqueAttr
nsslapd-pluginVersion: 1.1.0
diff --git a/install/updates/10-uniqueness.update b/install/updates/10-uniqueness.update
index fa17911f2..5c5bfd3e0 100644
--- a/install/updates/10-uniqueness.update
+++ b/install/updates/10-uniqueness.update
@@ -63,13 +63,32 @@ add:uniqueness-subtree-entries-oc: posixAccount
# krbPrincipalName uniqueness scopes Active/Delete containers
dn: cn=krbPrincipalName uniqueness,cn=plugins,cn=config
-add:uniqueness-exclude-subtrees: cn=staged users,cn=accounts,cn=provisioning,$SUFFIX
-add:uniqueness-across-all-subtrees: on
+deleteentry: cn=krbPrincipalName uniqueness,cn=plugins,cn=config
# krbCanonicalName uniqueness scopes Active/Delete containers
dn: cn=krbCanonicalName uniqueness,cn=plugins,cn=config
-add:uniqueness-exclude-subtrees: cn=staged users,cn=accounts,cn=provisioning,$SUFFIX
-add:uniqueness-across-all-subtrees: on
+deleteentry: dn: cn=krbCanonicalName uniqueness,cn=plugins,cn=config
+
+dn: cn=kerberos name uniqueness,cn=plugins,cn=config
+default:objectClass: top
+default:objectClass: nsSlapdPlugin
+default:objectClass: extensibleObject
+default:cn: kerberos name uniqueness
+default:nsslapd-pluginPath: libattr-unique-plugin
+default:nsslapd-pluginInitfunc: NSUniqueAttr_Init
+default:nsslapd-pluginType: preoperation
+default:nsslapd-pluginEnabled: on
+default:uniqueness-attribute-name: krbPrincipalName:CaseIgnoreMatch:
+default:uniqueness-attribute-name: krbPrincipalAlias:CaseIgnoreMatch:
+default:uniqueness-attribute-name: krbCanonicalName:CaseIgnoreMatch:
+default:nsslapd-plugin-depends-on-type: database
+default:nsslapd-pluginId: NSUniqueAttr
+default:nsslapd-pluginVersion: 1.1.0
+default:nsslapd-pluginVendor: Fedora Project
+default:nsslapd-pluginDescription: Enforce unique attribute values
+default:uniqueness-subtrees: $SUFFIX
+default:uniqueness-exclude-subtrees: cn=staged users,cn=accounts,cn=provisioning,$SUFFIX
+default:uniqueness-across-all-subtrees: on
# ipaUniqueID uniqueness scopes Active/Delete containers
dn: cn=ipaUniqueID uniqueness,cn=plugins,cn=config
--
2.50.1

View File

@ -0,0 +1,230 @@
From 4784cb826f7cfd01471c29cfb51bdf6d34d6d643 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Tue, 9 Sep 2025 12:45:24 -0300
Subject: [PATCH] ipa-kdb: enforce PAC presence on TGT for TGS-REQ
MS-KILE's PA-PAC-REQUEST sequence allows the Kerberos client to request
a TGT without a PAC. At the moment, there is no way to configure the MIT
KDC to reject such request.
This commit enforces the presence of the PAC when processing TGTs
provided by TGS-REQ. It ensures the server principal of the TGT is the
same as the one in PAC_CLIENT_INFO (i.e. enforces client principal
canonicalization) with integrity check.
Only one exception is applied: this check is skipped for local TGTs on
domain where the MS-PAC generator is not initialized (i.e. domains where
SID generation was not executed yet).
Signed-off-by: Julien Rische <jrische@redhat.com>
---
daemons/ipa-kdb/ipa_kdb.h | 9 +++
daemons/ipa-kdb/ipa_kdb_common.c | 18 ++++++
daemons/ipa-kdb/ipa_kdb_kdcpolicy.c | 2 +-
daemons/ipa-kdb/ipa_kdb_mspac.c | 87 ++++++++++++++++++++++++++++
daemons/ipa-kdb/ipa_kdb_principals.c | 21 +------
5 files changed, 116 insertions(+), 21 deletions(-)
diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h
index 85cabe142..7bad8c85f 100644
--- a/daemons/ipa-kdb/ipa_kdb.h
+++ b/daemons/ipa-kdb/ipa_kdb.h
@@ -434,6 +434,14 @@ ipadb_check_for_bronze_bit_attack(krb5_context context,
# endif
#endif
+/* Check the ticket provided in a TGS-REQ. In some situations, the ticket is
+ * expected to contain a PAC. If it is not the case, or if the function is
+ * enable to decode an authorization-data element, it fails.
+ * Any failure should result in the TGS-REQ to be rejected. */
+krb5_error_code ipadb_enforce_pac(krb5_context kcontext,
+ const krb5_ticket *ticket,
+ const char **status);
+
/* DELEGATION CHECKS */
krb5_error_code ipadb_check_allowed_to_delegate(krb5_context kcontext,
@@ -472,3 +480,4 @@ int ipadb_string_to_sid(const char *str, struct dom_sid *sid);
void alloc_sid(struct dom_sid **sid);
void free_sid(struct dom_sid **sid);
bool dom_sid_check(const struct dom_sid *sid1, const struct dom_sid *sid2, bool exact_check);
+bool ipadb_is_tgs_princ(krb5_context kcontext, krb5_const_principal princ);
diff --git a/daemons/ipa-kdb/ipa_kdb_common.c b/daemons/ipa-kdb/ipa_kdb_common.c
index 42e0856d0..eb0b0d129 100644
--- a/daemons/ipa-kdb/ipa_kdb_common.c
+++ b/daemons/ipa-kdb/ipa_kdb_common.c
@@ -704,3 +704,21 @@ krb5_error_code ipadb_multibase_search(struct ipadb_context *ipactx,
return ipadb_simple_ldap_to_kerr(ret);
}
+bool
+ipadb_is_tgs_princ(krb5_context kcontext, krb5_const_principal princ)
+{
+ krb5_data *primary;
+ size_t l_tgs_name;
+
+ if (2 != krb5_princ_size(kcontext, princ))
+ return false;
+
+ primary = krb5_princ_component(kcontext, princ, 0);
+
+ l_tgs_name = strlen(KRB5_TGS_NAME);
+
+ if (l_tgs_name != primary->length)
+ return false;
+
+ return 0 == memcmp(primary->data, KRB5_TGS_NAME, l_tgs_name);
+}
diff --git a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
index d6d618d1d..a92a9a0ad 100644
--- a/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
+++ b/daemons/ipa-kdb/ipa_kdb_kdcpolicy.c
@@ -207,7 +207,7 @@ ipa_kdcpolicy_check_tgs(krb5_context context, krb5_kdcpolicy_moddata moddata,
*lifetime_out = 0;
*renew_lifetime_out = 0;
- return 0;
+ return ipadb_enforce_pac(context, ticket, status);
}
krb5_error_code kdcpolicy_ipakdb_initvt(krb5_context context,
diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c
index 0964d112a..c4085fca5 100644
--- a/daemons/ipa-kdb/ipa_kdb_mspac.c
+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c
@@ -3344,6 +3344,93 @@ krb5_error_code ipadb_is_princ_from_trusted_realm(krb5_context kcontext,
return KRB5_KDB_NOENTRY;
}
+static krb5_error_code
+check_for_pac(krb5_context kcontext, krb5_authdata **authdata, bool *pac_present)
+{
+ krb5_error_code kerr = ENOENT;
+ size_t i, j;
+ krb5_authdata **ifrel = NULL;
+
+ for (i = 0; authdata && authdata[i]; ++i) {
+ if (authdata[i]->ad_type != KRB5_AUTHDATA_IF_RELEVANT) {
+ continue;
+ }
+
+ kerr = krb5_decode_authdata_container(kcontext,
+ KRB5_AUTHDATA_IF_RELEVANT,
+ authdata[i], &ifrel);
+ if (kerr) {
+ goto end;
+ }
+
+ for (j = 0; ifrel[j]; ++j) {
+ if (ifrel[j]->ad_type == KRB5_AUTHDATA_WIN2K_PAC) {
+ break;
+ }
+ }
+ if (ifrel[j]) {
+ break;
+ }
+
+ krb5_free_authdata(kcontext, ifrel);
+ ifrel = NULL;
+ }
+
+ *pac_present = ifrel;
+ kerr = 0;
+
+end:
+ krb5_free_authdata(kcontext, ifrel);
+ return kerr;
+}
+
+krb5_error_code
+ipadb_enforce_pac(krb5_context kcontext, const krb5_ticket *ticket,
+ const char **status)
+{
+ struct ipadb_context *ipactx;
+ bool pac_present;
+ krb5_error_code kerr;
+
+ /* Filter TGTs only */
+ if (!ipadb_is_tgs_princ(kcontext, ticket->server)) {
+ kerr = 0;
+ goto end;
+ }
+
+ /* Get IPA context */
+ ipactx = ipadb_get_context(kcontext);
+ if (!ipactx) {
+ kerr = KRB5_KDB_DBNOTINITED;
+ goto end;
+ }
+
+ /* If local TGT but PAC generator not initialized, skip PAC enforcement */
+ if (krb5_realm_compare(kcontext, ipactx->local_tgs, ticket->server) &&
+ !ipactx->mspac)
+ {
+ krb5_klog_syslog(LOG_WARNING, "MS-PAC not available. This makes "
+ "FreeIPA vulnerable to privilege escalation exploit "
+ "(CVE-2025-7493). Please generate SIDs to enable PAC "
+ "support.");
+ kerr = 0;
+ goto end;
+ }
+
+ /* Search for the PAC, fail if it cannot be found */
+ kerr = check_for_pac(kcontext, ticket->enc_part2->authorization_data,
+ &pac_present);
+ if (kerr) {
+ *status = "PAC_ENFORCEMENT_CANNOT_DECODE_TGT_AUTHDATA";
+ } else if (!pac_present) {
+ kerr = ENOENT;
+ *status = "PAC_ENFORCEMENT_TGT_WITHOUT_PAC";
+ }
+
+end:
+ return kerr;
+}
+
#if KRB5_KDB_DAL_MAJOR_VERSION <= 8
# ifdef HAVE_KRB5_PAC_FULL_SIGN_COMPAT
krb5_error_code
diff --git a/daemons/ipa-kdb/ipa_kdb_principals.c b/daemons/ipa-kdb/ipa_kdb_principals.c
index 6ee274053..11e084739 100644
--- a/daemons/ipa-kdb/ipa_kdb_principals.c
+++ b/daemons/ipa-kdb/ipa_kdb_principals.c
@@ -183,25 +183,6 @@ done:
return ret;
}
-static bool
-is_tgs_princ(krb5_context kcontext, krb5_const_principal princ)
-{
- krb5_data *primary;
- size_t l_tgs_name;
-
- if (2 != krb5_princ_size(kcontext, princ))
- return false;
-
- primary = krb5_princ_component(kcontext, princ, 0);
-
- l_tgs_name = strlen(KRB5_TGS_NAME);
-
- if (l_tgs_name != primary->length)
- return false;
-
- return 0 == memcmp(primary->data, KRB5_TGS_NAME, l_tgs_name);
-}
-
static krb5_error_code ipadb_set_tl_data(krb5_db_entry *entry,
krb5_int16 type,
krb5_ui_2 length,
@@ -1882,7 +1863,7 @@ krb5_error_code ipadb_get_principal(krb5_context kcontext,
#if KRB5_KDB_DAL_MAJOR_VERSION <= 8
/* If TGS principal, some virtual attributes may be added */
- if (is_tgs_princ(kcontext, (*entry)->princ)) {
+ if (ipadb_is_tgs_princ(kcontext, (*entry)->princ)) {
kerr = krb5_dbe_set_string(kcontext, *entry,
KRB5_KDB_SK_OPTIONAL_AD_SIGNEDPATH,
"true");
--
2.51.0

View File

@ -0,0 +1,93 @@
From d57d11974e05f84c0964ca941a6b507419b02211 Mon Sep 17 00:00:00 2001
From: Florence Blanc-Renaud <flo@redhat.com>
Date: Thu, 28 Aug 2025 15:31:39 +0200
Subject: [PATCH] ipatests: extend test for unique krbcanonicalname
Add a test ensuring that root@REALM cannot be added as
krbcanonicalname
Add a test for PAC enforcement:
try to access a service using a TGT obtained without PAC.
Should fail as PAC is now enforced.
Signed-off-by: Florence Blanc-Renaud <flo@redhat.com>
---
ipatests/test_integration/test_commands.py | 44 ++++++++++++++++++++--
1 file changed, 40 insertions(+), 4 deletions(-)
diff --git a/ipatests/test_integration/test_commands.py b/ipatests/test_integration/test_commands.py
index 38202c9a3fbc5e91c03a5953a5d9bec3c07117f4..c982c678aae047d5cb505889729bcb5bccbc3c20 100644
--- a/ipatests/test_integration/test_commands.py
+++ b/ipatests/test_integration/test_commands.py
@@ -1563,7 +1563,7 @@ def test_unique_krbcanonicalname(self):
hostname = master.hostname
realm = master.domain.realm
principal = f'test/{hostname}@{realm}'
- entry_ldif = textwrap.dedent("""
+ entry_ldif_template = textwrap.dedent("""
dn: krbprincipalname={principal},cn=services,cn=accounts,{base_dn}
changetype: add
ipakrbprincipalalias: test/{hostname}@{realm}
@@ -1573,13 +1573,15 @@ def test_unique_krbcanonicalname(self):
objectclass: krbprincipal
objectclass: krbprincipalaux
objectclass: top
- krbcanonicalname: admin@{realm}
+ krbcanonicalname: {user}@{realm}
managedby: fqdn={hostname},cn=computers,cn=accounts,{base_dn}
- """).format(
+ """)
+ entry_ldif = entry_ldif_template.format(
base_dn=base_dn,
hostname=hostname,
principal=principal,
- realm=realm)
+ realm=realm,
+ user='admin')
tasks.kdestroy_all(master)
master.run_command(
['kinit', '-kt', '/etc/krb5.keytab', f'host/{hostname}@{realm}'])
@@ -1592,6 +1594,40 @@ def test_unique_krbcanonicalname(self):
raiseonerr=False)
assert "entry with the same attribute value" in result.stderr_text
+ # Now try with root@realm instead of admin@realm
+ entry_ldif = entry_ldif_template.format(
+ base_dn=base_dn,
+ hostname=hostname,
+ principal=principal,
+ realm=realm,
+ user='root')
+ args = [
+ 'ldapmodify',
+ '-Y',
+ 'GSSAPI'
+ ]
+ result = master.run_command(args, stdin_text=entry_ldif,
+ raiseonerr=False)
+ assert "entry with the same attribute value" in result.stderr_text
+ tasks.kdestroy_all(master)
+
+ def test_no_request_pac(self):
+ # Try to use a TGT obtained without PAC
+ # Should fail as the presence of the PAC when processing TGTs
+ # provided by TGS-REQ is now enforced.
+ hostname = self.master.hostname
+ realm = self.master.domain.realm
+ self.master.run_command([
+ 'kinit', '-kt', '/etc/krb5.keytab', f'host/{hostname}@{realm}',
+ '--no-request-pac'
+ ])
+ result = self.master.run_command(
+ ['kvno', f'ldap/{hostname}@{realm}'],
+ raiseonerr=False
+ )
+ assert result.returncode == 1
+ assert "PAC_ENFORCEMENT_TGT_WITHOUT_PAC" in result.stderr_text
+
class TestIPACommandWithoutReplica(IntegrationTest):
"""
--
2.51.0

View File

@ -0,0 +1,173 @@
--- a/ipatests/test_integration/test_commands.py 2025-09-17 10:36:00.180673487 -0300
+++ b/ipatests/test_integration/test_commands.py 2025-09-17 10:37:31.294681273 -0300
@@ -1554,80 +1554,6 @@
assert result.returncode == 1
assert 'cannot be deleted or disabled' in result.stderr_text
- def test_unique_krbcanonicalname(self):
- """Verify that the uniqueness for krbcanonicalname is working"""
- master = self.master
-
- base_dn = str(master.domain.basedn)
- hostname = master.hostname
- realm = master.domain.realm
- principal = f'test/{hostname}@{realm}'
- entry_ldif_template = textwrap.dedent("""
- dn: krbprincipalname={principal},cn=services,cn=accounts,{base_dn}
- changetype: add
- ipakrbprincipalalias: test/{hostname}@{realm}
- krbprincipalname: {principal}
- objectclass: ipakrbprincipal
- objectclass: ipaobject
- objectclass: ipaservice
- objectclass: krbprincipal
- objectclass: krbprincipalaux
- objectclass: top
- krbcanonicalname: {user}@{realm}
- managedby: fqdn={hostname},cn=computers,cn=accounts,{base_dn}
- """)
- entry_ldif = entry_ldif_template.format(
- base_dn=base_dn,
- hostname=hostname,
- principal=principal,
- realm=realm,
- user='admin')
- tasks.kdestroy_all(master)
- master.run_command(
- ['kinit', '-kt', '/etc/krb5.keytab', f'host/{hostname}@{realm}'])
- args = [
- 'ldapmodify',
- '-Y',
- 'GSSAPI'
- ]
- result = master.run_command(args, stdin_text=entry_ldif,
- raiseonerr=False)
- assert "entry with the same attribute value" in result.stderr_text
-
- # Now try with root@realm instead of admin@realm
- entry_ldif = entry_ldif_template.format(
- base_dn=base_dn,
- hostname=hostname,
- principal=principal,
- realm=realm,
- user='root')
- args = [
- 'ldapmodify',
- '-Y',
- 'GSSAPI'
- ]
- result = master.run_command(args, stdin_text=entry_ldif,
- raiseonerr=False)
- assert "entry with the same attribute value" in result.stderr_text
- tasks.kdestroy_all(master)
-
- def test_no_request_pac(self):
- # Try to use a TGT obtained without PAC
- # Should fail as the presence of the PAC when processing TGTs
- # provided by TGS-REQ is now enforced.
- hostname = self.master.hostname
- realm = self.master.domain.realm
- self.master.run_command([
- 'kinit', '-kt', '/etc/krb5.keytab', f'host/{hostname}@{realm}',
- '--no-request-pac'
- ])
- result = self.master.run_command(
- ['kvno', f'ldap/{hostname}@{realm}'],
- raiseonerr=False
- )
- assert result.returncode == 1
- assert "PAC_ENFORCEMENT_TGT_WITHOUT_PAC" in result.stderr_text
-
class TestIPACommandWithoutReplica(IntegrationTest):
"""
@@ -1749,7 +1675,7 @@
api.bootstrap_with_global_options(context='server')
api.finalize()
api.Backend.ldap2.connect()
-
+
api.Command["group_add"]("testgroup1", external=True)
api.Command["group_add"]("testgroup2", external=False)
result1 = api.Command["group_show"]("testgroup1", all=True)["result"] # noqa: E501
@@ -1794,6 +1720,80 @@
'/tmp/reproducer2_code.py'])
assert "missing attribute" not in result.stdout_text
+ def test_unique_krbcanonicalname(self):
+ """Verify that the uniqueness for krbcanonicalname is working"""
+ master = self.master
+
+ base_dn = str(master.domain.basedn)
+ hostname = master.hostname
+ realm = master.domain.realm
+ principal = f'test/{hostname}@{realm}'
+ entry_ldif_template = textwrap.dedent("""
+ dn: krbprincipalname={principal},cn=services,cn=accounts,{base_dn}
+ changetype: add
+ ipakrbprincipalalias: test/{hostname}@{realm}
+ krbprincipalname: {principal}
+ objectclass: ipakrbprincipal
+ objectclass: ipaobject
+ objectclass: ipaservice
+ objectclass: krbprincipal
+ objectclass: krbprincipalaux
+ objectclass: top
+ krbcanonicalname: {user}@{realm}
+ managedby: fqdn={hostname},cn=computers,cn=accounts,{base_dn}
+ """)
+ entry_ldif = entry_ldif_template.format(
+ base_dn=base_dn,
+ hostname=hostname,
+ principal=principal,
+ realm=realm,
+ user='admin')
+ tasks.kdestroy_all(master)
+ master.run_command(
+ ['kinit', '-kt', '/etc/krb5.keytab', f'host/{hostname}@{realm}'])
+ args = [
+ 'ldapmodify',
+ '-Y',
+ 'GSSAPI'
+ ]
+ result = master.run_command(args, stdin_text=entry_ldif,
+ raiseonerr=False)
+ assert "entry with the same attribute value" in result.stderr_text
+
+ # Now try with root@realm instead of admin@realm
+ entry_ldif = entry_ldif_template.format(
+ base_dn=base_dn,
+ hostname=hostname,
+ principal=principal,
+ realm=realm,
+ user='root')
+ args = [
+ 'ldapmodify',
+ '-Y',
+ 'GSSAPI'
+ ]
+ result = master.run_command(args, stdin_text=entry_ldif,
+ raiseonerr=False)
+ assert "entry with the same attribute value" in result.stderr_text
+ tasks.kdestroy_all(master)
+
+ def test_no_request_pac(self):
+ # Try to use a TGT obtained without PAC
+ # Should fail as the presence of the PAC when processing TGTs
+ # provided by TGS-REQ is now enforced.
+ hostname = self.master.hostname
+ realm = self.master.domain.realm
+ self.master.run_command([
+ 'kinit', '-kt', '/etc/krb5.keytab', f'host/{hostname}@{realm}',
+ '--no-request-pac'
+ ])
+ result = self.master.run_command(
+ ['kvno', f'ldap/{hostname}@{realm}'],
+ raiseonerr=False
+ )
+ assert result.returncode == 1
+ assert "PAC_ENFORCEMENT_TGT_WITHOUT_PAC" in result.stderr_text
+
class TestIPAautomount(IntegrationTest):
@classmethod

View File

@ -32,7 +32,7 @@ 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
@@ -259,7 +259,6 @@ class BasePathNamespace:
@@ -258,8 +258,7 @@ 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"
@ -41,6 +41,7 @@ index 7d21367ec..42a47f1df 100644
- 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

View File

@ -74,7 +74,7 @@
%global python_ldap_version 3.1.0-1
%if 0%{?rhel} < 9
# Bug 1929067 - PKI instance creation failed with new 389-ds-base build
%global ds_version 1.4.3.16-12
%global ds_version 1.4.3.39-15
%else
%global ds_version 2.0.3-3
%endif
@ -190,7 +190,7 @@
Name: %{package_name}
Version: %{IPA_VERSION}
Release: 12%{?rc_version:.%rc_version}%{?dist}
Release: 20%{?rc_version:.%rc_version}%{?dist}
Summary: The Identity, Policy and Audit system
License: GPLv3+
@ -242,6 +242,17 @@ Patch0030: 0030-ipa-otptoken-import-open-the-key-file-in-binary-mode_rhel#3
Patch0031: 0031-ipa-crlgen-manage-manage-the-cert-status-task-execution-time_rhel#30280.patch
Patch0032: 0032-idrange-add-add-a-warning-because-389ds-restart-is-required_rhel#28996.patch
Patch0033: 0033-PKINIT-certificate-fix-renewal-on-hidden-replica_rhel#4913.patch
Patch0034: 0034-Add-ipa-idrange-fix_rhel#56920.patch
Patch0035: 0035-Unconditionally-add-MS-PAC-to-global-config-on-update_rhel#49437.patch
Patch0036: 0036-ipatests-Update-ipa-adtrust-install-test_rhel#40894.patch
Patch0037: 0037-Replica-CA-installation-ignore-skew-during-initial-replication_rhel#80995.patch
Patch0038: 0038-Add-a-check-into-ipa-cert-fix-tool-to-avoid-updating-certs-if-CA-is-close-to-being-expired_rhel#4941.patch
Patch0039: 0039-kdb-keeep-ipadb_get_connection-from-succeding-with-null-LDAP-context_rhel#58435.patch
Patch0040: 0040-Set-krbCanonicalName-admin-REALM-on-the-admin-user_rhel#89895.patch
Patch0041: 0041-Enforce-uniqueness-across-krbprincipalname-and-krbca_rhel#110061.patch
Patch0042: 0042-ipa-kdb-enforce-PAC-presence-on-TGT-for-TGS-REQ_rhel#110061.patch
Patch0043: 0043-ipatests-extend-test-for-unique-krbcanonicalname_rhel#110061.patch
Patch0044: 0044-ipatests-refactor-krb-unique-tests_rhel#110061.patch
%if 0%{?rhel} >= 8
Patch1001: 1001-Change-branding-to-IPA-and-Identity-Management.patch
Patch1002: 1002-Revert-freeipa.spec-depend-on-bind-dnssec-utils.patch
@ -402,7 +413,7 @@ BuildRequires: python3-pycodestyle
BuildRequires: python3-pylint
BuildRequires: python3-pytest-multihost
BuildRequires: python3-pytest-sourceorder
BuildRequires: python3-qrcode-core >= 5.0.0
BuildRequires: python3-qrcode-core >= 5.3
BuildRequires: python3-samba
BuildRequires: python3-six
BuildRequires: python3-sss
@ -1005,10 +1016,7 @@ for i in *.po ; do
done
popd
for p in %patches ; do
%__patch -p1 -i $p
UpdateTimestamps -p1 $p
done
%autopatch -p1
%build
# PATH is workaround for https://bugzilla.redhat.com/show_bug.cgi?id=1005235
@ -1403,6 +1411,7 @@ fi
%{_sbindir}/ipa-pkinit-manage
%{_sbindir}/ipa-crlgen-manage
%{_sbindir}/ipa-cert-fix
%{_sbindir}/ipa-idrange-fix
%{_sbindir}/ipa-acme-manage
%{_libexecdir}/certmonger/dogtag-ipa-ca-renew-agent-submit
%{_libexecdir}/certmonger/ipa-server-guard
@ -1477,6 +1486,7 @@ fi
%{_mandir}/man1/ipa-pkinit-manage.1*
%{_mandir}/man1/ipa-crlgen-manage.1*
%{_mandir}/man1/ipa-cert-fix.1*
%{_mandir}/man1/ipa-idrange-fix.1*
%{_mandir}/man1/ipa-acme-manage.1*
@ -1757,7 +1767,49 @@ fi
%endif
%changelog
* Wed Jul 17 2024 Rafael Jeffman <rjeffman@redhat.com> - 4.9.13-9
* Thu Sep 11 2025 Rafael Jeffman <rjeffman@redhat.com> - 4.9.13-20
- Refactor ipatests for unique krbcanonicalname
Resolves: RHEL-110061
* Thu Sep 11 2025 Rafael Jeffman <rjeffman@redhat.com> - 4.9.13-19
- Enforce uniqueness across krbprincipalname and krbcanonicalname
ipa-kdb: enforce PAC presence on TGT for TGS-REQ
ipatests: extend test for unique krbcanonicalname
Resolves: RHEL-110061
* Tue Jun 03 2025 Rafael Jeffman <rjeffman@redhat.com> - 4.9.13-18
- Set krbCanonicalName admin@REALM on the admin user
Resolves: RHEL-89895
* Mon May 19 2025 Rafael Jeffman <rjeffman@redhat.com> - 4.9.13-17
- kdb: keeep ipadb_get_connection() from succeding with null LDAP context
Resolves: RHEL-58453
* Mon Mar 31 2025 Rafael Jeffman <rjeffman@redhat.com> - 4.9.13-16
- Add a- heck into ipa-cert-fix tool to avoid updating certs if CA is close to expire
Resolves: RHEL-4941
- Fix rpminspect's 'patches' warnings
Resolves: RHEL-22497
* Mon Mar 10 2025 Rafael Jeffman <rjeffman@redhat.com> - 4.9.13-15
- Replica CA installation: ignore skew during initial replication
Resolves RHEL-80995
* Wed Nov 27 2024 Rafael Jeffman <rjeffman@redhat.com> - 4.9.13-14
- ipatests: Update ipa-adtrust-install test
Resolves: RHEL-40894
* Thu Nov 14 2024 Rafael Jeffman <rjeffman@redhat.com> - 4.9.13-13
- Add ipa-idrange-fix
Resolves: RHEL-56920
- Unconditionally add MS-PAC to global config on update
Resolves: RHEL-49437
- ipatests: Update ipa-adtrust-install test
Resolves: RHEL-40894
- Require python-qrcode version 5.3 or later
Related: RHEL-15090
* Wed Jul 17 2024 Rafael Jeffman <rjeffman@redhat.com> - 4.9.13-12
- Allow the admin user to be disabled
Resolves: RHEL-34756
- ipa-otptoken-import: open the key file in binary mode
@ -1905,7 +1957,7 @@ fi
* Thu May 25 2023 Rafael Jeffman <rjeffman@redhat.com> - 4.9.12-2
- Use the OpenSSL certificate parser in cert-find
Resolves: RHBZ#2209947
Resolves: RHBZ#2209947
* Wed May 24 2023 Rafael Jeffman <rjeffman@redhat.com> - 4.9.12-1
- Rebase ipa to 4.9.12
@ -1938,7 +1990,7 @@ fi
Resolves: RHBZ#2129895
- Fix canonicalization issue in Web UI
Resolves: RHBZ#2127035
- Remove idnssoaserial argument from dns zone API.
- Remove idnssoaserial argument from dns zone API.
Resolves: RHBZ#2108630
- Warn for permissions with read/write/search/compare and no attrs
Resolves: RHBZ#2098187