Browse Source

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 [email protected] (Thank you soooooo much, Mark!)
Noriko Hosoi 9 years ago
parent
commit
78f730ac36

+ 28 - 12
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;

+ 3 - 3
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();

+ 38 - 21
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();

+ 5 - 3
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_ */

+ 18 - 0
ldap/servers/slapd/slapi-plugin.h

@@ -4835,6 +4835,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.
  *

+ 1 - 0
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);
 
 /**

+ 74 - 1
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)
 {

+ 16 - 0
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)
 {