mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2026-10-24 22:27:41 -05:00
Merge branch 'upstream'
This commit is contained in:
commit
fd5e4cc17c
9 files changed
+185
-53
No files matched your search
+1
-1
@@ -21,7 +21,7 @@
|
||||
########################################################
|
||||
define(IPA_VERSION_MAJOR, 4)
|
||||
define(IPA_VERSION_MINOR, 12)
|
||||
define(IPA_VERSION_RELEASE, 4)
|
||||
define(IPA_VERSION_RELEASE, 5)
|
||||
|
||||
########################################################
|
||||
# For 'pre' releases the version will be #
|
||||
|
||||
@@ -431,6 +431,14 @@ krb5_error_code ipadb_is_princ_from_trusted_realm(krb5_context kcontext,
|
||||
const char *test_realm, size_t size,
|
||||
char **trusted_realm);
|
||||
|
||||
/* 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,
|
||||
@@ -475,3 +483,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);
|
||||
@@ -767,3 +767,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);
|
||||
}
|
||||
@@ -195,7 +195,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,
|
||||
|
||||
@@ -3346,3 +3346,90 @@ 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;
|
||||
}
|
||||
@@ -188,25 +188,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
|
||||
cmp_local_tgs_princ(krb5_context kcontext, const char *local_realm,
|
||||
krb5_const_principal princ, bool *result)
|
||||
@@ -1986,7 +1967,7 @@ krb5_error_code ipadb_get_principal(krb5_context kcontext,
|
||||
return kerr;
|
||||
|
||||
/* 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 = cmp_local_tgs_princ(kcontext, ipactx->realm, (*entry)->princ,
|
||||
&is_local_tgs_princ);
|
||||
if (kerr)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -80,13 +80,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
|
||||
|
||||
@@ -1891,7 +1891,7 @@ class TestIPACommandWithoutReplica(IntegrationTest):
|
||||
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}
|
||||
@@ -1902,13 +1902,15 @@ class TestIPACommandWithoutReplica(IntegrationTest):
|
||||
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}'])
|
||||
@@ -1921,6 +1923,40 @@ class TestIPACommandWithoutReplica(IntegrationTest):
|
||||
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
|
||||
|
||||
Reference in new issue
Block a user