ldap/servers/slapd/pw.c | 57 ++++++++++++++++++++++++++++++++----------------
1 file changed, 38 insertions(+), 19 deletions(-)
New commits:
commit f97797235463d73b10581680605d88c0eef546ac
Author: Noriko Hosoi <nhosoi(a)jiji.usersys.redhat.com>
Date: Wed Dec 15 18:14:48 2010 -0800
Bug 489379 - passwordExpirationTime in entry being added
collides with passwordMustChange policy
https://bugzilla.redhat.com/show_bug.cgi?id=489379
Description:
If we have passwordMustChange policy enabled and try to add an entry
that already contains an passwordExpirationTime attribute, then the
passwordMustChange code will insert another passwordExpirationTime
attribute with the magic 19700101000000Z value. This wont work
because passwordExpirationTime is single-valued:
ldap_add: Object class violation
ldap_add: additional info: single-valued attribute "passwordExpirationTime"
has multiple values
We need to pick one passwordExpirationTime value to "win". I think
it makes sense for the value that exists in the entry being added
to win, but I'm open to discussion if it's felt that would violate
the password policy.
To make the existing passwordExpirationTime value win, in
add_password_attrs() in pw.c I think the logic can be changed so
the scan for passwordExpirationTime happens unconditionally and
then not touch it even if pwpolicy->pw_must_change is set.
This patch has been submitted by Ulf Weltman (ulf.weltman(a)hp.com).
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
index 94a038f..22f818e 100644
--- a/ldap/servers/slapd/pw.c
+++ b/ldap/servers/slapd/pw.c
@@ -1321,44 +1321,63 @@ add_password_attrs( Slapi_PBlock *pb, Operation *op, Slapi_Entry
*e )
Slapi_Attr **a, **next;
passwdPolicy *pwpolicy = NULL;
char *dn = slapi_entry_get_ndn(e);
-
- pwpolicy = new_passwdPolicy(pb, dn);
+ int has_allowchangetime = 0, has_expirationtime = 0;
+ time_t existing_exptime = 0;
LDAPDebug( LDAP_DEBUG_TRACE, "add_password_attrs\n", 0, 0, 0 );
bvals[0] = &bv;
bvals[1] = NULL;
- if ( pwpolicy->pw_must_change) {
- /* must change password when first time logon */
- bv.bv_val = format_genTime ( NO_TIME );
- } else {
- /* If passwordexpirationtime is specified by the user, don't
- try to assign the initial value */
- for ( a = &e->e_attrs; *a != NULL; a = next ) {
- if ( strcasecmp( (*a)->a_type,
- "passwordexpirationtime" ) == 0) {
- delete_passwdPolicy(&pwpolicy);
- return;
+ /* If passwordexpirationtime is specified by the user, don't
+ try to assign the initial value */
+ for ( a = &e->e_attrs; *a != NULL; a = next ) {
+ if ( strcasecmp( (*a)->a_type,
+ "passwordexpirationtime" ) == 0) {
+ Slapi_Value *sval;
+ if (slapi_attr_first_value(*a, &sval) == 0) {
+ const struct berval *bv = slapi_value_get_berval(sval);
+ existing_exptime = parse_genTime(bv->bv_val);
}
- next = &(*a)->a_next;
+ has_expirationtime = 1;
+
+ } else if ( strcasecmp( (*a)->a_type,
+ "passwordallowchangetime" ) == 0) {
+ has_allowchangetime = 1;
}
+ next = &(*a)->a_next;
+ }
- bv.bv_val = format_genTime ( time_plus_sec ( current_time (),
- pwpolicy->pw_maxage ) );
+ if ( has_allowchangetime && has_expirationtime ) {
+ return;
}
- if ( pwpolicy->pw_exp || pwpolicy->pw_must_change ) {
+
+ pwpolicy = new_passwdPolicy(pb, dn);
+
+ if ( !has_expirationtime &&
+ ( pwpolicy->pw_exp || pwpolicy->pw_must_change ) ) {
+ if ( pwpolicy->pw_must_change) {
+ /* must change password when first time logon */
+ bv.bv_val = format_genTime ( NO_TIME );
+ } else if ( pwpolicy->pw_exp ) {
+ bv.bv_val = format_genTime ( time_plus_sec ( current_time (),
+ pwpolicy->pw_maxage ) );
+ }
bv.bv_len = strlen( bv.bv_val );
slapi_entry_attr_merge( e, "passwordexpirationtime", bvals );
+ slapi_ch_free_string( &bv.bv_val );
}
- slapi_ch_free((void **) &bv.bv_val );
/*
* If the password minimum age is not 0, calculate when the password
* is allowed to be changed again and store the result
* in passwordallowchangetime in the user's entry.
+ * If the password has expired, don't add passwordallowchangetime,
+ * otherwise if the user has grace logins, they can't be used to change
+ * the password if we set a passwordallowchangetime in the future.
*/
- if ( pwpolicy->pw_minage != 0 ) {
+ if ( !has_allowchangetime && pwpolicy->pw_minage != 0 &&
+ (has_expirationtime && existing_exptime > current_time()) ) {
bv.bv_val = format_genTime ( time_plus_sec ( current_time (),
pwpolicy->pw_minage ) );
bv.bv_len = strlen( bv.bv_val );