mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2024-12-24 16:10:02 -06:00
Implement user pre-authentication control with kdcpolicy plugin
We created a Kerberos kdcpolicy plugin to enforce user pre-authentication policy for newly added pkinit and hardened policy. In the past version of freeIPA, password enforcement exists but was done by removing key data for a principal while parsing LDAP entry for it. This hack is also removed and is now also enforced by kdcpolicy plugin instead. Resolves: https://pagure.io/freeipa/issue/8001 Signed-off-by: Changmin Teng <cteng@redhat.com> Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com> Reviewed-By: Simo Sorce <ssorce@redhat.com> Reviewed-By: Robbie Harwood <rharwood@redhat.com>
This commit is contained in:
parent
179c8f4009
commit
15ff9c8fec
@ -141,6 +141,7 @@ struct ipadb_e_data {
|
||||
time_t last_admin_unlock;
|
||||
char **authz_data;
|
||||
bool has_tktpolaux;
|
||||
enum ipadb_user_auth user_auth;
|
||||
};
|
||||
|
||||
struct ipadb_context *ipadb_get_context(krb5_context kcontext);
|
||||
|
@ -18,12 +18,82 @@ ipa_kdcpolicy_check_as(krb5_context context, krb5_kdcpolicy_moddata moddata,
|
||||
const char **status, krb5_deltat *lifetime_out,
|
||||
krb5_deltat *renew_lifetime_out)
|
||||
{
|
||||
krb5_error_code kerr;
|
||||
enum ipadb_user_auth ua;
|
||||
struct ipadb_e_data *ied;
|
||||
int valid_auth_indicators = 0;
|
||||
|
||||
*status = NULL;
|
||||
*lifetime_out = 0;
|
||||
*renew_lifetime_out = 0;
|
||||
|
||||
krb5_klog_syslog(LOG_INFO, "IPA kdcpolicy: checking AS-REQ.");
|
||||
|
||||
ied = (struct ipadb_e_data *)client->e_data;
|
||||
if (ied == NULL || ied->magic != IPA_E_DATA_MAGIC) {
|
||||
/* e-data is not availble, getting user auth from LDAP */
|
||||
krb5_klog_syslog(LOG_INFO, "IPA kdcpolicy: client e_data not availble. Try fetching...");
|
||||
kerr = ipadb_get_principal(context, request->client, KRB5_KDB_FLAG_ALIAS_OK, &client);
|
||||
if (kerr != 0) {
|
||||
krb5_klog_syslog(LOG_ERR, "IPA kdcpolicy: ipadb_find_principal failed.");
|
||||
return kerr;
|
||||
}
|
||||
|
||||
ied = (struct ipadb_e_data *)client->e_data;
|
||||
if (ied == NULL && ied->magic != IPA_E_DATA_MAGIC) {
|
||||
krb5_klog_syslog(LOG_ERR, "IPA kdcpolicy: client e_data fetching failed.");
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
ua = ied->user_auth;
|
||||
|
||||
/* If no mechanisms are set, allow every auth method */
|
||||
if (ua == IPADB_USER_AUTH_NONE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* For each auth indicator, see if it is allowed for that user */
|
||||
for (int i = 0; auth_indicators[i] != NULL; i++) {
|
||||
const char *auth_indicator = auth_indicators[i];
|
||||
|
||||
if (strcmp(auth_indicator, "otp") == 0) {
|
||||
valid_auth_indicators++;
|
||||
if (!(ua & IPADB_USER_AUTH_OTP)) {
|
||||
*status = "OTP pre-authentication not allowed for this user.";
|
||||
return KRB5KDC_ERR_POLICY;
|
||||
}
|
||||
} else if (strcmp(auth_indicator, "radius") == 0) {
|
||||
valid_auth_indicators++;
|
||||
if (!(ua & IPADB_USER_AUTH_RADIUS)) {
|
||||
*status = "OTP pre-authentication not allowed for this user.";
|
||||
return KRB5KDC_ERR_POLICY;
|
||||
}
|
||||
} else if (strcmp(auth_indicator, "pkinit") == 0) {
|
||||
valid_auth_indicators++;
|
||||
if (!(ua & IPADB_USER_AUTH_PKINIT)) {
|
||||
*status = "PKINIT pre-authentication not allowed for this user.";
|
||||
return KRB5KDC_ERR_POLICY;
|
||||
}
|
||||
} else if (strcmp(auth_indicator, "hardened") == 0) {
|
||||
valid_auth_indicators++;
|
||||
/* Allow hardened even if only password pre-auth is allowed */
|
||||
if (!(ua & (IPADB_USER_AUTH_HARDENED | IPADB_USER_AUTH_PASSWORD))) {
|
||||
*status = "Password pre-authentication not not allowed for this user.";
|
||||
return KRB5KDC_ERR_POLICY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* There is no auth indicator assigned for non-hardened password authentication
|
||||
* so we assume password is used when no supported indicator exists */
|
||||
if (!valid_auth_indicators) {
|
||||
if (!(ua & IPADB_USER_AUTH_PASSWORD)) {
|
||||
*status = "Non-hardened password authentication not allowed for this user.";
|
||||
return KRB5KDC_ERR_POLICY;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -318,15 +318,6 @@ static void ipadb_validate_radius(struct ipadb_context *ipactx,
|
||||
ldap_value_free_len(vals);
|
||||
}
|
||||
|
||||
static void ipadb_validate_password(struct ipadb_context *ipactx,
|
||||
LDAPMessage *lentry,
|
||||
enum ipadb_user_auth *ua)
|
||||
{
|
||||
/* If no mechanisms are set, use password. */
|
||||
if (*ua == IPADB_USER_AUTH_NONE)
|
||||
*ua |= IPADB_USER_AUTH_PASSWORD;
|
||||
}
|
||||
|
||||
static enum ipadb_user_auth ipadb_get_user_auth(struct ipadb_context *ipactx,
|
||||
LDAPMessage *lentry)
|
||||
{
|
||||
@ -354,7 +345,6 @@ 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_password(ipactx, lentry, &ua);
|
||||
|
||||
return ua;
|
||||
}
|
||||
@ -708,13 +698,6 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
|
||||
&res_key_data, &result, &mkvno);
|
||||
switch (ret) {
|
||||
case 0:
|
||||
/* Only set a principal's key if password auth should be used. */
|
||||
if (!(ua & IPADB_USER_AUTH_PASSWORD)) {
|
||||
/* This is the same behavior as ENOENT below. */
|
||||
ipa_krb5_free_key_data(res_key_data, result);
|
||||
break;
|
||||
}
|
||||
|
||||
entry->key_data = res_key_data;
|
||||
entry->n_key_data = result;
|
||||
if (mkvno) {
|
||||
@ -851,6 +834,8 @@ static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext,
|
||||
ied->authz_data = authz_data_list;
|
||||
}
|
||||
|
||||
ied->user_auth = ua;
|
||||
|
||||
/* If enabled, set the otp user string, enabling otp. */
|
||||
if (ua & IPADB_USER_AUTH_OTP) {
|
||||
kerr = ipadb_set_tl_data(entry, KRB5_TL_STRING_ATTRS,
|
||||
|
Loading…
Reference in New Issue
Block a user