ipa-kdb: initial support for passkeys

- added passkey detection based on the presence of ipaPassKey attribute
  in the LDAP entry of the principal
- added 'passkey' authentication indicator
- added support for enforcing KDC policy based on the 'passkey'
  indicator

Fixes: https://pagure.io/freeipa/issue/9263
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
This commit is contained in:
Alexander Bokovoy authored and Florence Blanc-Renaud committed 2023-06-01 08:20:37 +02:00
1 parent d207f6bf32
commit 56e179748b
4 files changed
+43

No files matched your search

+1
View File
@@ -200,6 +200,7 @@ static const struct {
{ "pkinit", IPADB_USER_AUTH_PKINIT },
{ "hardened", IPADB_USER_AUTH_HARDENED },
{ "idp", IPADB_USER_AUTH_IDP },
{ "passkey", IPADB_USER_AUTH_PASSKEY },
{ }
};
+2
View File
@@ -106,6 +106,7 @@ enum ipadb_user_auth {
IPADB_USER_AUTH_PKINIT = 1 << 4,
IPADB_USER_AUTH_HARDENED = 1 << 5,
IPADB_USER_AUTH_IDP = 1 << 6,
IPADB_USER_AUTH_PASSKEY = 1 << 7,
};
enum ipadb_user_auth_idx {
@@ -114,6 +115,7 @@ enum ipadb_user_auth_idx {
IPADB_USER_AUTH_IDX_PKINIT,
IPADB_USER_AUTH_IDX_HARDENED,
IPADB_USER_AUTH_IDX_IDP,
IPADB_USER_AUTH_IDX_PASSKEY,
IPADB_USER_AUTH_IDX_MAX,
};
+9
View File
@@ -143,6 +143,15 @@ ipa_kdcpolicy_check_as(krb5_context context, krb5_kdcpolicy_moddata moddata,
goto done;
}
pol_limits = &(ied->pol_limits[IPADB_USER_AUTH_IDX_IDP]);
} else if (strcmp(auth_indicator, "passkey") == 0) {
valid_auth_indicators++;
/* Allow hardened even if only password pre-auth is allowed */
if (!(ua & IPADB_USER_AUTH_PASSKEY)) {
*status = "Passkey pre-authentication not allowed for this user.";
kerr = KRB5KDC_ERR_POLICY;
goto done;
}
pol_limits = &(ied->pol_limits[IPADB_USER_AUTH_IDX_PASSKEY]);
}
}
+31
View File
@@ -78,6 +78,7 @@ static char *std_principal_attrs[] = {
IPA_USER_AUTH_TYPE,
"ipatokenRadiusConfigLink",
"ipaIdpConfigLink",
"ipaPassKey",
"krbAuthIndMaxTicketLife",
"krbAuthIndMaxRenewableAge",
"ipaNTSecurityIdentifier",
@@ -396,6 +397,25 @@ static void ipadb_validate_idp(struct ipadb_context *ipactx,
ldap_value_free_len(vals);
}
static void ipadb_validate_passkey(struct ipadb_context *ipactx,
LDAPMessage *lentry,
enum ipadb_user_auth *ua)
{
struct berval **vals;
if (!(*ua & IPADB_USER_AUTH_PASSKEY))
return;
/* Ensure that the user has a link to an IdP config. */
vals = ldap_get_values_len(ipactx->lcontext, lentry,
"ipaPassKey");
if (vals == NULL || vals[0] == NULL)
*ua &= ~IPADB_USER_AUTH_PASSKEY;
if (vals != NULL)
ldap_value_free_len(vals);
}
static enum ipadb_user_auth ipadb_get_user_auth(struct ipadb_context *ipactx,
LDAPMessage *lentry)
{
@@ -429,6 +449,7 @@ static enum ipadb_user_auth ipadb_get_user_auth(struct ipadb_context *ipactx,
ipadb_validate_otp(ipactx, lentry, &ua);
ipadb_validate_radius(ipactx, lentry, &ua);
ipadb_validate_idp(ipactx, lentry, &ua);
ipadb_validate_passkey(ipactx, lentry, &ua);
return ua;
}
@@ -613,6 +634,8 @@ static void ipadb_parse_authind_policies(krb5_context kcontext,
IPADB_USER_AUTH_HARDENED, IPADB_USER_AUTH_IDX_HARDENED},
{"krbAuthIndMaxTicketLife;idp",
IPADB_USER_AUTH_IDP, IPADB_USER_AUTH_IDX_IDP},
{"krbAuthIndMaxTicketLife;passkey",
IPADB_USER_AUTH_PASSKEY, IPADB_USER_AUTH_IDX_PASSKEY},
{NULL, IPADB_USER_AUTH_NONE, IPADB_USER_AUTH_IDX_MAX},
}, age_authind_map[] = {
{"krbAuthIndMaxRenewableAge;otp",
@@ -625,6 +648,8 @@ static void ipadb_parse_authind_policies(krb5_context kcontext,
IPADB_USER_AUTH_HARDENED, IPADB_USER_AUTH_IDX_HARDENED},
{"krbAuthIndMaxRenewableAge;idp",
IPADB_USER_AUTH_IDP, IPADB_USER_AUTH_IDX_IDP},
{"krbAuthIndMaxRenewableAge;passkey",
IPADB_USER_AUTH_PASSKEY, IPADB_USER_AUTH_IDX_PASSKEY},
{NULL, IPADB_USER_AUTH_NONE, IPADB_USER_AUTH_IDX_MAX},
};
@@ -668,6 +693,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\"]}]";
const krb5_octet passkey_string[] = "passkey\0[{\"indicators\": [\"passkey\"]}]";
struct ipadb_context *ipactx;
enum ipadb_user_auth ua;
LDAP *lcontext;
@@ -1052,6 +1078,11 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
sizeof(idp_string), idp_string);
if (kerr)
goto done;
} else if (ua & IPADB_USER_AUTH_PASSKEY) {
kerr = ipadb_set_tl_data(entry, KRB5_TL_STRING_ATTRS,
sizeof(passkey_string), passkey_string);
if (kerr)
goto done;
}
if (ua & ~IPADB_USER_AUTH_NONE) {