ldap/servers/slapd/libglobs.c | 40 +++++++++++++------
ldap/servers/slapd/proto-slap.h | 6 +-
ldap/servers/slapd/pw.c | 59 ++++++++++++++++++-----------
ldap/servers/slapd/slap.h | 8 ++-
ldap/servers/slapd/slapi-plugin.h | 18 ++++++++
ldap/servers/slapd/slapi-private.h | 1
ldap/servers/slapd/time.c | 75 ++++++++++++++++++++++++++++++++++++-
ldap/servers/slapd/value.c | 16 +++++++
8 files changed, 183 insertions(+), 40 deletions(-)
New commits:
commit 78f730ac363761c159423543767e7cc4bc34d4ed
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Fri Jun 3 16:22:32 2016 -0700
Ticket #48833 - 389 showing inconsistent values for shadowMax and shadowWarning in
1.3.5.1
Description: Current passwordMaxAge, passwordMinAge, and passwordWarning
internally have the integer type which is too small to hold the maximum
shadowMax value 99999 days (== 8,639,913,600 secs > INT_MAX 2,147,483,647).
To allow shadowMax and its friends in sync with the values in the password
policy, this patch changes the type of the pw_maxage, pw_minage, and pw_
warning from long to long long.
If password policy is enabled, and the value of passwordMaxAge is greater
than 8639913600:
passwordMaxAge: 8639913600
then the search returns shadowMax 99999.
$ ldapsearch [...] -b "uid=tuser,ou=People,dc=example,dc=com" shadowMax
dn: uid=tuser,ou=People,dc=example,dc=com
shadowMax: 99999
Note: This patch is setting the initial value of passwordMaxAge to 99999 days.
cfg->pw_policy.pw_maxage = 8639913600; /* 99999 days */
Requires: This change requires the Doc and the DS Console updates.
https://fedorahosted.org/389/ticket/48833
Reviewed by mreynolds(a)redhat.com (Thank you soooooo much, Mark!)
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index a9334e4..aa77783 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -1546,7 +1546,11 @@ FrontendConfig_init () {
cfg->pw_policy.pw_maxrepeats = 0;
cfg->pw_policy.pw_mincategories = 3;
cfg->pw_policy.pw_mintokenlength = 3;
+#if defined(CPU_x86_64)
+ cfg->pw_policy.pw_maxage = 8639913600; /* 99999 days */
+#else
cfg->pw_policy.pw_maxage = 8640000; /* 100 days */
+#endif
cfg->pw_policy.pw_minage = 0;
cfg->pw_policy.pw_warning = _SEC_PER_DAY; /* 1 day */
init_pw_history = cfg->pw_policy.pw_history = LDAP_OFF;
@@ -4360,7 +4364,7 @@ config_set_auditfaillog( const char *attrname, char *value, char
*errorbuf, int
int
config_set_pw_maxage( const char *attrname, char *value, char *errorbuf, int apply ) {
int retVal = LDAP_SUCCESS;
- long age;
+ long long age;
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
@@ -4370,9 +4374,15 @@ config_set_pw_maxage( const char *attrname, char *value, char
*errorbuf, int app
errno = 0;
/* age in seconds */
- age = parse_duration(value);
+ age = slapi_parse_duration_longlong(value);
- if ( age <= 0 || age > (MAX_ALLOWED_TIME_IN_SECS - current_time()) ) {
+ if (age <= 0 ||
+#if defined(CPU_x86_64)
+ age > (MAX_ALLOWED_TIME_IN_SECS_64 - current_time())
+#else
+ age > (MAX_ALLOWED_TIME_IN_SECS - current_time())
+#endif
+ ) {
slapi_create_errormsg(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, "%s: password maximum
age \"%s\" is invalid.", attrname, value);
retVal = LDAP_OPERATIONS_ERROR;
return retVal;
@@ -4387,7 +4397,7 @@ config_set_pw_maxage( const char *attrname, char *value, char
*errorbuf, int app
int
config_set_pw_minage( const char *attrname, char *value, char *errorbuf, int apply ) {
int retVal = LDAP_SUCCESS;
- long age;
+ long long age;
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
if ( config_value_is_null( attrname, value, errorbuf, 1 )) {
@@ -4396,8 +4406,14 @@ config_set_pw_minage( const char *attrname, char *value, char
*errorbuf, int app
errno = 0;
/* age in seconds */
- age = parse_duration(value);
- if ( age < 0 || age > (MAX_ALLOWED_TIME_IN_SECS - current_time()) ) {
+ age = slapi_parse_duration_longlong(value);
+ if (age < 0 ||
+#if defined(CPU_x86_64)
+ age > (MAX_ALLOWED_TIME_IN_SECS_64 - current_time())
+#else
+ age > (MAX_ALLOWED_TIME_IN_SECS - current_time())
+#endif
+ ) {
slapi_create_errormsg(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, "%s: password minimum
age \"%s\" is invalid.", attrname, value);
retVal = LDAP_OPERATIONS_ERROR;
return retVal;
@@ -4412,7 +4428,7 @@ config_set_pw_minage( const char *attrname, char *value, char
*errorbuf, int app
int
config_set_pw_warning( const char *attrname, char *value, char *errorbuf, int apply ) {
int retVal = LDAP_SUCCESS;
- long sec;
+ long long sec;
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
@@ -4422,7 +4438,7 @@ config_set_pw_warning( const char *attrname, char *value, char
*errorbuf, int ap
errno = 0;
/* in seconds */
- sec = parse_duration(value);
+ sec = slapi_parse_duration_longlong(value);
if (errno == ERANGE || sec < 0) {
slapi_create_errormsg(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
@@ -5699,10 +5715,10 @@ config_get_auditfaillog( ){
return retVal;
}
-long
+long long
config_get_pw_maxage() {
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
- long retVal;
+ long long retVal;
CFG_LOCK_READ(slapdFrontendConfig);
retVal = slapdFrontendConfig->pw_policy.pw_maxage;
@@ -5710,7 +5726,7 @@ config_get_pw_maxage() {
return retVal;
}
-long
+long long
config_get_pw_minage(){
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
@@ -5723,7 +5739,7 @@ config_get_pw_minage(){
return retVal;
}
-long
+long long
config_get_pw_warning() {
slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
long retVal;
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 1de1e38..7e0e632 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -490,9 +490,9 @@ char *config_get_accesslog();
char *config_get_errorlog();
char *config_get_auditlog();
char *config_get_auditfaillog();
-long config_get_pw_maxage();
-long config_get_pw_minage();
-long config_get_pw_warning();
+long long config_get_pw_maxage();
+long long config_get_pw_minage();
+long long config_get_pw_warning();
int config_get_errorlog_level();
int config_get_accesslog_level();
int config_get_auditlog_logging_enabled();
diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c
index c52fa9b..498afd4 100644
--- a/ldap/servers/slapd/pw.c
+++ b/ldap/servers/slapd/pw.c
@@ -1821,7 +1821,7 @@ new_passwdPolicy(Slapi_PBlock *pb, const char *dn)
slapi_attr_get_type(attr, &attr_name);
if (!strcasecmp(attr_name, "passwordminage")) {
if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_minage = slapi_value_get_timelong(*sval);
+ pwdpolicy->pw_minage = slapi_value_get_timelonglong(*sval);
if (-1 == pwdpolicy->pw_minage) {
LDAPDebug2Args(LDAP_DEBUG_ANY,
"Password Policy Entry%s: Invalid passwordMinAge: %s\n",
@@ -1833,7 +1833,7 @@ new_passwdPolicy(Slapi_PBlock *pb, const char *dn)
else
if (!strcasecmp(attr_name, "passwordmaxage")) {
if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_maxage = slapi_value_get_timelong(*sval);
+ pwdpolicy->pw_maxage = slapi_value_get_timelonglong(*sval);
if (-1 == pwdpolicy->pw_maxage) {
LDAPDebug2Args(LDAP_DEBUG_ANY,
"Password Policy Entry%s: Invalid passwordMaxAge: %s\n",
@@ -1845,7 +1845,7 @@ new_passwdPolicy(Slapi_PBlock *pb, const char *dn)
else
if (!strcasecmp(attr_name, "passwordwarning")) {
if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_warning = slapi_value_get_timelong(*sval);
+ pwdpolicy->pw_warning = slapi_value_get_timelonglong(*sval);
if (-1 == pwdpolicy->pw_warning) {
LDAPDebug2Args(LDAP_DEBUG_ANY,
"Password Policy Entry%s: Invalid passwordWarning: %s\n",
@@ -2201,15 +2201,19 @@ check_pw_duration_value(const char *attr_name, char *value,
long minval, long maxval, char *errorbuf, size_t ebuflen)
{
int retVal = LDAP_SUCCESS;
- long age;
+ long long age;
- age = parse_duration(value);
+ age = slapi_parse_duration_longlong(value);
if (-1 == age) {
slapi_create_errormsg(errorbuf, ebuflen, "password minimum age \"%s\" is
invalid. ", value);
retVal = LDAP_CONSTRAINT_VIOLATION;
} else if (0 == strcasecmp(CONFIG_PW_LOCKDURATION_ATTRIBUTE, attr_name)) {
if ( (age <= 0) ||
+#if defined(CPU_x86_64)
+ (age > (MAX_ALLOWED_TIME_IN_SECS_64 - current_time())) ||
+#else
(age > (MAX_ALLOWED_TIME_IN_SECS - current_time())) ||
+#endif
((-1 != minval) && (age < minval)) ||
((-1 != maxval) && (age > maxval))) {
slapi_create_errormsg(errorbuf, ebuflen, "%s: \"%s\" seconds is
invalid. ", attr_name, value);
@@ -2217,7 +2221,11 @@ check_pw_duration_value(const char *attr_name, char *value,
}
} else {
if ( (age < 0) ||
+#if defined(CPU_x86_64)
+ (age > (MAX_ALLOWED_TIME_IN_SECS_64 - current_time())) ||
+#else
(age > (MAX_ALLOWED_TIME_IN_SECS - current_time())) ||
+#endif
((-1 != minval) && (age < minval)) ||
((-1 != maxval) && (age > maxval))) {
slapi_create_errormsg(errorbuf, ebuflen, "%s: \"%s\" seconds is
invalid. ", attr_name, value);
@@ -2867,11 +2875,11 @@ add_shadow_ext_password_attrs(Slapi_PBlock *pb, Slapi_Entry **e)
{
const char *dn = NULL;
passwdPolicy *pwpolicy = NULL;
- time_t shadowval = 0;
- time_t exptime = 0;
+ long long shadowval = 0;
+ long long exptime = 0;
Slapi_Mods *smods = NULL;
LDAPMod **mods;
- long sval;
+ long long sval;
int mod_num = 0;
char *shmin = NULL;
char *shmax = NULL;
@@ -2904,59 +2912,68 @@ add_shadow_ext_password_attrs(Slapi_PBlock *pb, Slapi_Entry **e)
/* shadowMin - the minimum number of days required between password changes. */
if (pwpolicy->pw_minage > 0) {
shadowval = pwpolicy->pw_minage / _SEC_PER_DAY;
+ if (shadowval > _MAX_SHADOW) {
+ shadowval = _MAX_SHADOW;
+ }
} else {
shadowval = 0;
}
shmin = slapi_entry_attr_get_charptr(*e, "shadowMin");
if (shmin) {
- sval = strtol(shmin, NULL, 0);
+ sval = strtoll(shmin, NULL, 0);
if (sval != shadowval) {
slapi_ch_free_string(&shmin);
- shmin = slapi_ch_smprintf("%ld", shadowval);
+ shmin = slapi_ch_smprintf("%lld", shadowval);
mod_num++;
}
} else {
mod_num++;
- shmin = slapi_ch_smprintf("%ld", shadowval);
+ shmin = slapi_ch_smprintf("%lld", shadowval);
}
/* shadowMax - the maximum number of days for which the user password remains valid.
*/
if (pwpolicy->pw_maxage > 0) {
shadowval = pwpolicy->pw_maxage / _SEC_PER_DAY;
exptime = time_plus_sec(current_time(), pwpolicy->pw_maxage);
+ if (shadowval > _MAX_SHADOW) {
+ shadowval = _MAX_SHADOW;
+ }
} else {
- shadowval = 99999;
+ shadowval = _MAX_SHADOW;
}
shmax = slapi_entry_attr_get_charptr(*e, "shadowMax");
if (shmax) {
- sval = strtol(shmax, NULL, 0);
+ sval = strtoll(shmax, NULL, 0);
if (sval != shadowval) {
slapi_ch_free_string(&shmax);
- shmax = slapi_ch_smprintf("%ld", shadowval);
+ shmax = slapi_ch_smprintf("%lld", shadowval);
mod_num++;
}
} else {
mod_num++;
- shmax = slapi_ch_smprintf("%ld", shadowval);
+ shmax = slapi_ch_smprintf("%lld", shadowval);
}
/* shadowWarning - the number of days of advance warning given to the user before the
user password expires. */
if (pwpolicy->pw_warning > 0) {
shadowval = pwpolicy->pw_warning / _SEC_PER_DAY;
+ if (shadowval > _MAX_SHADOW) {
+ shadowval = _MAX_SHADOW;
+ }
} else {
shadowval = 0;
}
shwarn = slapi_entry_attr_get_charptr(*e, "shadowWarning");
if (shwarn) {
- sval = strtol(shwarn, NULL, 0);
+ sval = strtoll(shwarn, NULL, 0);
if (sval != shadowval) {
slapi_ch_free_string(&shwarn);
- shwarn = slapi_ch_smprintf("%ld", shadowval);
+ shwarn = slapi_ch_smprintf("%lld", shadowval);
mod_num++;
}
} else {
mod_num++;
- shwarn = slapi_ch_smprintf("%ld", shadowval);
+ shwarn = slapi_ch_smprintf("%lld", shadowval);
}
/* shadowExpire - the date on which the user login will be disabled. */
@@ -2964,15 +2981,15 @@ add_shadow_ext_password_attrs(Slapi_PBlock *pb, Slapi_Entry **e)
shexp = slapi_entry_attr_get_charptr(*e, "shadowExpire");
exptime /= _SEC_PER_DAY;
if (shexp) {
- sval = strtol(shexp, NULL, 0);
+ sval = strtoll(shexp, NULL, 0);
if (sval != exptime) {
slapi_ch_free_string(&shexp);
- shexp = slapi_ch_smprintf("%ld", shadowval);
+ shexp = slapi_ch_smprintf("%lld", exptime);
mod_num++;
}
} else {
mod_num++;
- shexp = slapi_ch_smprintf("%ld", exptime);
+ shexp = slapi_ch_smprintf("%lld", exptime);
}
}
smods = slapi_mods_new();
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index 52bdc8b..b74f9bd 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -1573,9 +1573,9 @@ typedef struct passwordpolicyarray {
int pw_mintokenlength;
slapi_onoff_t pw_exp;
slapi_onoff_t pw_send_expiring;
- long pw_maxage;
- long pw_minage;
- long pw_warning;
+ long long pw_maxage;
+ long long pw_minage;
+ long long pw_warning;
slapi_onoff_t pw_history;
int pw_inhistory;
slapi_onoff_t pw_lockout;
@@ -2200,6 +2200,7 @@ typedef struct _slapdEntryPoints {
#define REFER_MODE_ON 1
#define MAX_ALLOWED_TIME_IN_SECS 2147483647
+#define MAX_ALLOWED_TIME_IN_SECS_64 9223372036854775807
typedef struct _slapdFrontendConfig {
#if SLAPI_CFG_USE_RWLOCK == 1
@@ -2589,5 +2590,6 @@ extern char *attr_dataversion;
#define RUV_STORAGE_ENTRY_UNIQUEID "ffffffff-ffffffff-ffffffff-ffffffff"
#define _SEC_PER_DAY 86400
+#define _MAX_SHADOW 99999
#endif /* _slap_h_ */
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 32c0db1..a7e544a 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -4836,6 +4836,24 @@ unsigned long long slapi_value_get_ulonglong(const Slapi_Value
*value);
long slapi_value_get_timelong(const Slapi_Value *value);
/**
+ * Retrieves the value of a \c Slapi_Value structure as a long long integer.
+ *
+ * \param value Pointer to the value you wish to get as a long long integer.
+ * The value could end with D or d for days, H or h for hours,
+ * M or m for minutes, S or s for seconds, or no extension.
+ * \return A long long integer that corresponds to the value stored in the
+ * \c Slapi_Value structure.
+ * \return \c 0 if there is no value.
+ * \return \c -1 if the given value is invalid.
+ * \see slapi_value_get_int()
+ * \see slapi_value_get_uint()
+ * \see slapi_value_get_ulong()
+ * \see slapi_value_get_longlong()
+ * \see slapi_value_get_ulonglong()
+ */
+long long slapi_value_get_timelonglong(const Slapi_Value *value);
+
+/**
* Gets the length of a value contained in a \c Slapi_Value structure.
*
* \param value Pointer to the value of which you wish to get the length.
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
index a5efdda..7636559 100644
--- a/ldap/servers/slapd/slapi-private.h
+++ b/ldap/servers/slapd/slapi-private.h
@@ -1335,6 +1335,7 @@ char *slapi_getSSLVersion_str(PRUint16 vnum, char *buf, size_t
bufsize);
* Failure: -1
*/
time_t slapi_parse_duration(const char *value);
+long long slapi_parse_duration_longlong(const char *value);
int slapi_is_duration_valid(const char *value);
/**
diff --git a/ldap/servers/slapd/time.c b/ldap/servers/slapd/time.c
index d98b94b..4471a6f 100644
--- a/ldap/servers/slapd/time.c
+++ b/ldap/servers/slapd/time.c
@@ -517,7 +517,74 @@ parse_duration(char *value)
duration *= times;
bail:
if (duration == -1) {
- LDAPDebug1Arg(LDAP_DEBUG_ANY, "slapi_parse_duration: invalid duration
(%s)\n", value?value:"null");
+ LDAPDebug1Arg(LDAP_DEBUG_ANY, "parse_duration: invalid duration
(%s)\n", value?value:"null");
+ }
+ slapi_ch_free_string(&input);
+ return duration;
+}
+
+long long
+parse_duration_longlong(char *value)
+{
+ char *input = NULL;
+ char *endp;
+ long long duration = -1;
+ int times = 1;
+
+ if (NULL == value || '\0' == *value) {
+ goto bail;
+ }
+ input = slapi_ch_strdup(value);
+ endp = input + strlen(input) - 1;
+ while ((' ' == *endp || '\t' == *endp) && endp > input) {
+ endp--;
+ }
+ if ((endp == input) && !isdigit(*input)) {
+ goto bail;
+ }
+ switch ( *endp ) {
+ case 'w':
+ case 'W':
+ times = 60 * 60 * 24 * 7;
+ *endp = '\0';
+ break;
+ case 'd':
+ case 'D':
+ times = 60 * 60 * 24;
+ *endp = '\0';
+ break;
+ case 'h':
+ case 'H':
+ times = 60 * 60;
+ *endp = '\0';
+ break;
+ case 'm':
+ case 'M':
+ times = 60;
+ *endp = '\0';
+ break;
+ case 's':
+ case 'S':
+ times = 1;
+ *endp = '\0';
+ break;
+ default:
+ if (isdigit(*endp)) {
+ times = 1;
+ break;
+ } else {
+ goto bail;
+ }
+ }
+ duration = strtoll(input, &endp, 10);
+ if ( *endp != '\0' || errno == ERANGE ) {
+ duration = -1;
+ goto bail;
+ }
+ duration *= times;
+bail:
+ if (duration == -1) {
+ LDAPDebug1Arg(LDAP_DEBUG_ANY, "parse_duration_longlong: invalid duration
(%s)\n", value?value:"null");
}
slapi_ch_free_string(&input);
return duration;
@@ -529,6 +596,12 @@ slapi_parse_duration(const char *value)
return (time_t)parse_duration((char *)value);
}
+long long
+slapi_parse_duration_longlong(const char *value)
+{
+ return parse_duration_longlong((char *)value);
+}
+
static int
is_valid_duration_unit(const char value)
{
diff --git a/ldap/servers/slapd/value.c b/ldap/servers/slapd/value.c
index 51beff7..6eaa4cf 100644
--- a/ldap/servers/slapd/value.c
+++ b/ldap/servers/slapd/value.c
@@ -509,6 +509,22 @@ slapi_value_get_timelong(const Slapi_Value *value)
return r;
}
+long long
+slapi_value_get_timelonglong(const Slapi_Value *value)
+{
+ long long r = 0;
+ if(value)
+ {
+ char *p;
+ p = slapi_ch_malloc(value->bv.bv_len + 1);
+ memcpy(p, value->bv.bv_val, value->bv.bv_len);
+ p[value->bv.bv_len] = '\0';
+ r = slapi_parse_duration_longlong(p);
+ slapi_ch_free_string(&p);
+ }
+ return r;
+}
+
int
slapi_value_compare(const Slapi_Attr *a,const Slapi_Value *v1,const Slapi_Value *v2)
{