KDB: support external IdP configuration

When IdP configuration is provided, take it into account:

 - idp-specific Kerberos ticket policy would be applied

 - Presence of IdP link in a Kerberos principal entry would cause KDB to
   enable `idp` pre-authentication method on KDC side.

The latter requires additional pre-authentication method supplied with
SSSD 2.7.0.

Fixes: https://pagure.io/freeipa/issue/8804

Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
Signed-off-by: Pavel Březina <pbrezina@redhat.com>
Reviewed-By: Francisco Trivino <ftrivino@redhat.com>
Reviewed-By: Sumit Bose <sbose@redhat.com>
This commit is contained in:
Alexander Bokovoy 2022-05-03 11:49:27 +03:00
parent 3f6656e09a
commit a1be4fc863
4 changed files with 49 additions and 2 deletions

View File

@ -199,6 +199,7 @@ static const struct {
{ "otp", IPADB_USER_AUTH_OTP },
{ "pkinit", IPADB_USER_AUTH_PKINIT },
{ "hardened", IPADB_USER_AUTH_HARDENED },
{ "idp", IPADB_USER_AUTH_IDP },
{ }
};

View File

@ -89,6 +89,7 @@ enum ipadb_user_auth {
IPADB_USER_AUTH_OTP = 1 << 3,
IPADB_USER_AUTH_PKINIT = 1 << 4,
IPADB_USER_AUTH_HARDENED = 1 << 5,
IPADB_USER_AUTH_IDP = 1 << 6,
};
enum ipadb_user_auth_idx {
@ -96,6 +97,7 @@ enum ipadb_user_auth_idx {
IPADB_USER_AUTH_IDX_RADIUS,
IPADB_USER_AUTH_IDX_PKINIT,
IPADB_USER_AUTH_IDX_HARDENED,
IPADB_USER_AUTH_IDX_IDP,
IPADB_USER_AUTH_IDX_MAX,
};

View File

@ -133,6 +133,15 @@ ipa_kdcpolicy_check_as(krb5_context context, krb5_kdcpolicy_moddata moddata,
goto done;
}
pol_limits = &(ied->pol_limits[IPADB_USER_AUTH_IDX_HARDENED]);
} else if (strcmp(auth_indicator, "idp") == 0) {
valid_auth_indicators++;
/* Allow hardened even if only password pre-auth is allowed */
if (!(ua & IPADB_USER_AUTH_IDP)) {
*status = "IdP pre-authentication not allowed for this user.";
kerr = KRB5KDC_ERR_POLICY;
goto done;
}
pol_limits = &(ied->pol_limits[IPADB_USER_AUTH_IDX_IDP]);
}
}

View File

@ -77,6 +77,7 @@ static char *std_principal_attrs[] = {
IPA_KRB_AUTHZ_DATA_ATTR,
IPA_USER_AUTH_TYPE,
"ipatokenRadiusConfigLink",
"ipaIdpConfigLink",
"krbAuthIndMaxTicketLife",
"krbAuthIndMaxRenewableAge",
"ipaNTSecurityIdentifier",
@ -316,8 +317,31 @@ static void ipadb_validate_radius(struct ipadb_context *ipactx,
"ipatokenRadiusConfigLink");
if (vals == NULL || vals[0] == NULL)
*ua &= ~IPADB_USER_AUTH_RADIUS;
else
*ua = IPADB_USER_AUTH_RADIUS;
else {
/* OTP use implies presence of password in IPA LDAP,
* this is incompatible with RADIUS proxy case where
* a password in LDAP is not used anymore. */
*ua &= ~IPADB_USER_AUTH_OTP;
}
if (vals != NULL)
ldap_value_free_len(vals);
}
static void ipadb_validate_idp(struct ipadb_context *ipactx,
LDAPMessage *lentry,
enum ipadb_user_auth *ua)
{
struct berval **vals;
if (!(*ua & IPADB_USER_AUTH_IDP))
return;
/* Ensure that the user has a link to an IdP config. */
vals = ldap_get_values_len(ipactx->lcontext, lentry,
"ipaIdpConfigLink");
if (vals == NULL || vals[0] == NULL)
*ua &= ~IPADB_USER_AUTH_IDP;
if (vals != NULL)
ldap_value_free_len(vals);
@ -355,6 +379,7 @@ static enum ipadb_user_auth ipadb_get_user_auth(struct ipadb_context *ipactx,
/* Perform flag validation. */
ipadb_validate_otp(ipactx, lentry, &ua);
ipadb_validate_radius(ipactx, lentry, &ua);
ipadb_validate_idp(ipactx, lentry, &ua);
return ua;
}
@ -537,6 +562,8 @@ static void ipadb_parse_authind_policies(krb5_context kcontext,
IPADB_USER_AUTH_PKINIT, IPADB_USER_AUTH_IDX_PKINIT},
{"krbAuthIndMaxTicketLife;hardened",
IPADB_USER_AUTH_HARDENED, IPADB_USER_AUTH_IDX_HARDENED},
{"krbAuthIndMaxTicketLife;idp",
IPADB_USER_AUTH_IDP, IPADB_USER_AUTH_IDX_IDP},
{NULL, IPADB_USER_AUTH_NONE, IPADB_USER_AUTH_IDX_MAX},
}, age_authind_map[] = {
{"krbAuthIndMaxRenewableAge;otp",
@ -547,6 +574,8 @@ static void ipadb_parse_authind_policies(krb5_context kcontext,
IPADB_USER_AUTH_PKINIT, IPADB_USER_AUTH_IDX_PKINIT},
{"krbAuthIndMaxRenewableAge;hardened",
IPADB_USER_AUTH_HARDENED, IPADB_USER_AUTH_IDX_HARDENED},
{"krbAuthIndMaxRenewableAge;idp",
IPADB_USER_AUTH_IDP, IPADB_USER_AUTH_IDX_IDP},
{NULL, IPADB_USER_AUTH_NONE, IPADB_USER_AUTH_IDX_MAX},
};
@ -583,6 +612,7 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
{
const krb5_octet rad_string[] = "otp\0[{\"indicators\": [\"radius\"]}]";
const krb5_octet otp_string[] = "otp\0[{\"indicators\": [\"otp\"]}]";
const krb5_octet idp_string[] = "idp\0[{\"type\":\"oauth2\",\"indicators\": [\"idp\"]}]";
struct ipadb_context *ipactx;
enum ipadb_user_auth ua;
LDAP *lcontext;
@ -961,6 +991,11 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
sizeof(rad_string), rad_string);
if (kerr)
goto done;
} else if (ua & IPADB_USER_AUTH_IDP) {
kerr = ipadb_set_tl_data(entry, KRB5_TL_STRING_ATTRS,
sizeof(idp_string), idp_string);
if (kerr)
goto done;
}
if (ua & ~IPADB_USER_AUTH_NONE) {