kdb = calloc(1, sizeof(*kdb));
if (kdb == NULL)
return ENOMEM;
+
+ /* In all cases the principal entry is new and key data is set; let the
+ * database provider know. */
+ kdb->mask = mask | KADM5_KEY_DATA | KADM5_PRINCIPAL;
+
memset(&adb, 0, sizeof(osa_princ_ent_rec));
/*
kdb->expiration = handle->params.expiration;
kdb->pw_expiration = 0;
- if (have_polent) {
- if(polent.pw_max_life)
- kdb->pw_expiration = ts_incr(now, polent.pw_max_life);
- else
- kdb->pw_expiration = 0;
- }
- if ((mask & KADM5_PW_EXPIRATION))
+ if (mask & KADM5_PW_EXPIRATION) {
kdb->pw_expiration = entry->pw_expiration;
+ } else if (have_polent && polent.pw_max_life) {
+ kdb->mask |= KADM5_PW_EXPIRATION;
+ kdb->pw_expiration = ts_incr(now, polent.pw_max_life);
+ }
kdb->last_success = 0;
kdb->last_failed = 0;
adb.policy = entry->policy;
}
- /* In all cases key and the principal data is set, let the database provider know */
- kdb->mask = mask | KADM5_KEY_DATA | KADM5_PRINCIPAL ;
-
/* store the new db entry */
ret = kdb_put_entry(handle, kdb, &adb);
if (ret)
return(ret);
+ /* Let the mask propagate to the database provider. */
+ kdb->mask = mask;
+
/*
* This is pretty much the same as create ...
*/
free(adb.policy);
adb.policy = strdup(entry->policy);
}
- if (have_pol) {
+
+ if (mask & KADM5_PW_EXPIRATION) {
+ kdb->pw_expiration = entry->pw_expiration;
+ } else if (have_pol) {
/* set pw_max_life based on new policy */
+ kdb->mask |= KADM5_PW_EXPIRATION;
if (pol.pw_max_life) {
ret = krb5_dbe_lookup_last_pwd_change(handle->context, kdb,
- &(kdb->pw_expiration));
+ &kdb->pw_expiration);
if (ret)
goto done;
kdb->pw_expiration = ts_incr(kdb->pw_expiration, pol.pw_max_life);
kdb->max_life = entry->max_life;
if ((mask & KADM5_PRINC_EXPIRE_TIME))
kdb->expiration = entry->princ_expire_time;
- if (mask & KADM5_PW_EXPIRATION)
- kdb->pw_expiration = entry->pw_expiration;
if (mask & KADM5_MAX_RLIFE)
kdb->max_renewable_life = entry->max_renewable_life;
kdb->fail_auth_count = 0;
}
- /* let the mask propagate to the database provider */
- kdb->mask = mask;
-
ret = k5_kadm5_hook_modify(handle->context, handle->hook_handles,
KADM5_HOOK_STAGE_PRECOMMIT, entry, mask);
if (ret)
if ((ret = kdb_get_entry(handle, principal, &kdb, &adb)))
return(ret);
+ /* We will always be changing the key data, attributes, auth failure count,
+ * and password expiration time. */
+ kdb->mask = KADM5_KEY_DATA | KADM5_ATTRIBUTES | KADM5_FAIL_AUTH_COUNT |
+ KADM5_PW_EXPIRATION;
+
ret = apply_keysalt_policy(handle, adb.policy, n_ks_tuple, ks_tuple,
&new_n_ks_tuple, &new_ks_tuple);
if (ret)
if (ret)
goto done;
+ kdb->pw_expiration = 0;
if ((adb.aux_attributes & KADM5_POLICY)) {
/* the policy was loaded before */
if (pol.pw_max_life)
kdb->pw_expiration = ts_incr(now, pol.pw_max_life);
- else
- kdb->pw_expiration = 0;
- } else {
- kdb->pw_expiration = 0;
}
#ifdef USE_PASSWORD_SERVER
/* unlock principal on this KDC */
kdb->fail_auth_count = 0;
- /* key data and attributes changed, let the database provider know */
- kdb->mask = KADM5_KEY_DATA | KADM5_ATTRIBUTES |
- KADM5_FAIL_AUTH_COUNT;
- /* | KADM5_CPW_FUNCTION */
-
if (hist_added)
kdb->mask |= KADM5_KEY_HIST;
if ((ret = kdb_get_entry(handle, principal, &kdb, &adb)))
return(ret);
+ /* We will always be changing the key data, attributes, auth failure count,
+ * and password expiration time. */
+ kdb->mask = KADM5_KEY_DATA | KADM5_ATTRIBUTES | KADM5_FAIL_AUTH_COUNT |
+ KADM5_PW_EXPIRATION;
+
ret = apply_keysalt_policy(handle, adb.policy, n_ks_tuple, ks_tuple,
&new_n_ks_tuple, &new_ks_tuple);
if (ret)
if (ret)
goto done;
}
- if (have_pol) {
- if (pol.pw_max_life)
- kdb->pw_expiration = ts_incr(now, pol.pw_max_life);
- else
- kdb->pw_expiration = 0;
- } else {
- kdb->pw_expiration = 0;
- }
+
+ kdb->pw_expiration = 0;
+ if (have_pol && pol.pw_max_life)
+ kdb->pw_expiration = ts_incr(now, pol.pw_max_life);
ret = krb5_dbe_update_last_pwd_change(handle->context, kdb, now);
if (ret)
goto done;
}
- /* key data changed, let the database provider know */
- kdb->mask = KADM5_KEY_DATA | KADM5_FAIL_AUTH_COUNT;
- /* | KADM5_RANDKEY_USED */;
-
ret = k5_kadm5_hook_chpass(handle->context, handle->hook_handles,
KADM5_HOOK_STAGE_PRECOMMIT, principal, keepold,
new_n_ks_tuple, new_ks_tuple, NULL);
if (ret)
return ret;
+ /* We will always be changing the key data, attributes, auth failure count,
+ * and password expiration time. */
+ kdb->mask = KADM5_KEY_DATA | KADM5_ATTRIBUTES | KADM5_FAIL_AUTH_COUNT |
+ KADM5_PW_EXPIRATION;
+
if (kvno == 0) {
/* Pick the next kvno. */
for (i = 0; i < kdb->n_key_data; i++) {
if (ret)
goto done;
}
- if (have_pol) {
- if (pol.pw_max_life)
- kdb->pw_expiration = ts_incr(now, pol.pw_max_life);
- else
- kdb->pw_expiration = 0;
- } else {
- kdb->pw_expiration = 0;
- }
+
+ kdb->pw_expiration = 0;
+ if (have_pol && pol.pw_max_life)
+ kdb->pw_expiration = ts_incr(now, pol.pw_max_life);
ret = krb5_dbe_update_last_pwd_change(handle->context, kdb, now);
if (ret)
/* Unlock principal on this KDC. */
kdb->fail_auth_count = 0;
- /* key data changed, let the database provider know */
- kdb->mask = KADM5_KEY_DATA | KADM5_FAIL_AUTH_COUNT;
-
ret = kdb_put_entry(handle, kdb, &adb);
if (ret)
goto done;
realm.run([kadminl, 'modprinc', '-pwexpire', '2040-02-03', 'user'])
realm.run([kadminl, 'getprinc', 'user'], expected_msg=' 2040\n')
+# Regression test for #8861 (pw_expiration policy enforcement).
+mark('pw_expiration propogation')
+# Create a policy with a max life and verify its application.
+realm.run([kadminl, 'addpol', '-maxlife', '1s', 'pw_e'])
+realm.run([kadminl, 'addprinc', '-policy', 'pw_e', '-pw', 'password',
+ 'pwuser'])
+out = realm.run([kadminl, 'getprinc', 'pwuser'],
+ expected_msg='Password expiration date: ')
+if 'Password expiration date: [never]' in out:
+ fail('pw_expiration not applied at principal creation')
+# Unset the policy max life and verify its application during password
+# change.
+realm.run([kadminl, 'modpol', '-maxlife', '0', 'pw_e'])
+realm.run([kadminl, 'cpw', '-pw', 'password_', 'pwuser'])
+realm.run([kadminl, 'getprinc', 'pwuser'],
+ expected_msg='Password expiration date: [never]')
+
realm.stop()
# Briefly test dump and load.