kadm5: move password quality checks out of daemons and into libkadm5
Note that this has a slight behavior change to c89d3f3b
in order to continue
allow kadmin in local mode to bypass password quality checks. Password quality
checks are always bypassed if the *client* kadmin principal is kadmin/admin,
i.e. that of the kadmin service itself. This is the case when running kadmin in
local mode. As this is the equivalent of a superuser account, one would
anticipate that deployments would use specific administrator instances for
appropriate ACLs for day-to-day administration; operations by these will be
subject to password quality checks if enforce_on_admin_set is TRUE, or if the
user is changing their own password.
This commit is contained in:

committed by
Nico Williams

parent
62c1790bf5
commit
c6bf100b43
@@ -141,6 +141,21 @@ fetch_acl (kadm5_server_context *context,
|
||||
return ret;
|
||||
}
|
||||
|
||||
krb5_boolean
|
||||
_kadm5_is_kadmin_service_p(kadm5_server_context *context)
|
||||
{
|
||||
krb5_boolean ret;
|
||||
krb5_principal princ;
|
||||
|
||||
if (krb5_parse_name(context->context, KADM5_ADMIN_SERVICE, &princ) != 0)
|
||||
return FALSE;
|
||||
|
||||
ret = krb5_principal_compare(context->context, context->caller, princ);
|
||||
krb5_free_principal(context->context, princ);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* set global acl flags in `context' for the current caller.
|
||||
* return 0 on success or an error
|
||||
@@ -149,15 +164,7 @@ fetch_acl (kadm5_server_context *context,
|
||||
kadm5_ret_t
|
||||
_kadm5_acl_init(kadm5_server_context *context)
|
||||
{
|
||||
krb5_principal princ;
|
||||
krb5_error_code ret;
|
||||
|
||||
ret = krb5_parse_name(context->context, KADM5_ADMIN_SERVICE, &princ);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = krb5_principal_compare(context->context, context->caller, princ);
|
||||
krb5_free_principal(context->context, princ);
|
||||
if(ret != 0) {
|
||||
if (_kadm5_is_kadmin_service_p(context)) {
|
||||
context->acl_flags = KADM5_PRIV_ALL;
|
||||
return 0;
|
||||
}
|
||||
|
@@ -88,6 +88,23 @@ change(void *server_handle,
|
||||
uint32_t hook_flags = 0;
|
||||
|
||||
memset(&ent, 0, sizeof(ent));
|
||||
|
||||
if (krb5_principal_compare(context->context, princ, context->caller) ||
|
||||
_kadm5_enforce_pwqual_on_admin_set_p(context)) {
|
||||
krb5_data pwd_data;
|
||||
const char *pwd_reason;
|
||||
|
||||
pwd_data.data = rk_UNCONST(password);
|
||||
pwd_data.length = strlen(password);
|
||||
|
||||
pwd_reason = kadm5_check_password_quality(context->context,
|
||||
princ, &pwd_data);
|
||||
if (pwd_reason != NULL) {
|
||||
krb5_set_error_message(context->context, KADM5_PASS_Q_DICT, "%s", pwd_reason);
|
||||
return KADM5_PASS_Q_DICT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!context->keep_open) {
|
||||
ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0);
|
||||
if(ret)
|
||||
@@ -324,3 +341,18 @@ kadm5_s_chpass_principal_with_key(void *server_handle,
|
||||
}
|
||||
return _kadm5_error_code(ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns TRUE if password quality should be checked when passwords are
|
||||
* being set or changed by administrators. This includes principal creation.
|
||||
*/
|
||||
krb5_boolean
|
||||
_kadm5_enforce_pwqual_on_admin_set_p(kadm5_server_context *contextp)
|
||||
{
|
||||
if (_kadm5_is_kadmin_service_p(contextp))
|
||||
return FALSE;
|
||||
|
||||
return krb5_config_get_bool_default(contextp->context, NULL, TRUE,
|
||||
"password_quality",
|
||||
"enforce_on_admin_set", NULL);
|
||||
}
|
||||
|
@@ -212,6 +212,21 @@ kadm5_s_create_principal(void *server_handle,
|
||||
hdb_entry_ex ent;
|
||||
kadm5_server_context *context = server_handle;
|
||||
|
||||
if (_kadm5_enforce_pwqual_on_admin_set_p(context)) {
|
||||
krb5_data pwd_data;
|
||||
const char *pwd_reason;
|
||||
|
||||
pwd_data.data = rk_UNCONST(password);
|
||||
pwd_data.length = strlen(password);
|
||||
|
||||
pwd_reason = kadm5_check_password_quality(context->context,
|
||||
princ->principal, &pwd_data);
|
||||
if (pwd_reason != NULL) {
|
||||
krb5_set_error_message(context->context, KADM5_PASS_Q_DICT, "%s", pwd_reason);
|
||||
return KADM5_PASS_Q_DICT;
|
||||
}
|
||||
}
|
||||
|
||||
if ((mask & KADM5_KVNO) == 0) {
|
||||
/* create_principal() through _kadm5_setup_entry(), will need this */
|
||||
princ->kvno = 1;
|
||||
|
Reference in New Issue
Block a user