Browse Source

Bug 627993 - Inconsistent storage of password expiry times

https://bugzilla.redhat.com/show_bug.cgi?id=627993

Description: Allows passwordLockoutDuration, passwordResetFailureCount,
passwordMaxAge, passwordMinAge, passwordWarning to have <days>D|d,
<hours>H|h, <min>M|m, and <sec>S|s in addition to the current
representation <sec> in seconds.
Noriko Hosoi 15 years ago
parent
commit
5727b88997
3 changed files with 102 additions and 39 deletions
  1. 16 34
      ldap/servers/slapd/libglobs.c
  2. 2 4
      ldap/servers/slapd/slapi-private.h
  3. 84 1
      ldap/servers/slapd/time.c

+ 16 - 34
ldap/servers/slapd/libglobs.c

@@ -2163,7 +2163,6 @@ int
 config_set_pw_lockduration( const char *attrname, char *value, char *errorbuf, int apply ) {
   int retVal = LDAP_SUCCESS;
   long duration = 0; /* in minutes */
-  char *endp = NULL;
 
   slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
   
@@ -2173,11 +2172,11 @@ config_set_pw_lockduration( const char *attrname, char *value, char *errorbuf, i
 
   errno = 0;
   /* in seconds */
-  duration = strtol(value, &endp, 10);
+  duration = parse_duration(value);
 
-  if ( *endp != '\0' || errno == ERANGE || duration <= 0 || duration > (MAX_ALLOWED_TIME_IN_SECS - current_time()) ) {
+  if ( errno == ERANGE || duration <= 0 || duration > (MAX_ALLOWED_TIME_IN_SECS - current_time()) ) {
 	PR_snprintf ( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, 
-			  "password lockout duration \"%s\" seconds is invalid. ",
+			  "password lockout duration \"%s\" is invalid. ",
 			  value );
 	retVal = LDAP_OPERATIONS_ERROR;
 	return retVal;
@@ -2195,7 +2194,6 @@ int
 config_set_pw_resetfailurecount( const char *attrname, char *value, char *errorbuf, int apply ) {
   int retVal = LDAP_SUCCESS;
   long duration = 0; /* in minutes */
-  char *endp = NULL;
 
   slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
   
@@ -2205,11 +2203,11 @@ config_set_pw_resetfailurecount( const char *attrname, char *value, char *errorb
 
   errno = 0;
   /* in seconds */  
-  duration = strtol(value, &endp, 10);
+  duration = parse_duration(value);
 
-  if ( *endp != '\0' || errno == ERANGE || duration < 0 || duration > (MAX_ALLOWED_TIME_IN_SECS - current_time()) ) {
+  if ( errno == ERANGE || duration < 0 || duration > (MAX_ALLOWED_TIME_IN_SECS - current_time()) ) {
 	PR_snprintf ( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, 
-			  "password reset count duration \"%s\" seconds is invalid. ",
+			  "password reset count duration \"%s\" is invalid. ",
 			  value );
 	retVal = LDAP_OPERATIONS_ERROR;
 	return retVal;
@@ -3269,7 +3267,6 @@ int
 config_set_pw_maxage( const char *attrname, char *value, char *errorbuf, int apply ) {
   int retVal = LDAP_SUCCESS;
   long age;
-  char *endp = NULL;
 
   slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
   
@@ -3279,11 +3276,11 @@ config_set_pw_maxage( const char *attrname, char *value, char *errorbuf, int app
   
   errno = 0;
   /* age in seconds */
-  age = strtol(value, &endp, 10);
+  age = parse_duration(value);
 
-  if ( *endp != '\0' || errno == ERANGE || age <= 0 || age > (MAX_ALLOWED_TIME_IN_SECS - current_time()) ) {
+  if ( age <= 0 || age > (MAX_ALLOWED_TIME_IN_SECS - current_time()) ) {
 	PR_snprintf ( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, 
-			  "%s: password maximum age \"%s\" seconds is invalid. ",
+			  "%s: password maximum age \"%s\" is invalid. ",
 			  attrname, value );
 	retVal = LDAP_OPERATIONS_ERROR;
 	return retVal;
@@ -3299,7 +3296,6 @@ int
 config_set_pw_minage( const char *attrname, char *value, char *errorbuf, int apply ) {
   int retVal = LDAP_SUCCESS;
   long age;
-  char *endPtr = NULL;
   slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
   
   if ( config_value_is_null( attrname, value, errorbuf, 1 )) {
@@ -3308,24 +3304,11 @@ config_set_pw_minage( const char *attrname, char *value, char *errorbuf, int app
   
   errno = 0;
   /* age in seconds */
-  age = strtol(value, &endPtr, 0 );
-  /* endPtr should never be NULL, but we check just in case; if the
-	 value contains no digits, or a string that does not begin with
-	 a valid digit (e.g. "z2"), the days will be 0, and endPtr will
-	 point to the beginning of value; if days contains at least 1
-	 valid digit string, endPtr will point to the character after
-	 the end of the first valid digit string in value.  Example:
-	 value = "   2 3 " endPtr will point at the space character
-	 between the 2 and the 3.  So, we should be able to simply
-	 check to see if the character at *(endPtr - 1) is a digit.
-	 */
-  if ( (age < 0) || 
-		(age > (MAX_ALLOWED_TIME_IN_SECS - current_time())) ||
-	   (endPtr == NULL) || (endPtr == value) || !isdigit(*(endPtr-1)) ||
-            errno == ERANGE ) {
+  age = parse_duration(value);
+  if ( age < 0 || age > (MAX_ALLOWED_TIME_IN_SECS - current_time()) ) {
 	PR_snprintf ( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, 
-			   "%s: password minimum age \"%s\" seconds is invalid. ",
-			   attrname, value );
+			  "%s: password minimum age \"%s\" is invalid. ",
+			  attrname, value );
 	retVal = LDAP_OPERATIONS_ERROR;
 	return retVal;
   }
@@ -3340,7 +3323,6 @@ int
 config_set_pw_warning( const char *attrname, char *value, char *errorbuf, int apply ) {
   int retVal = LDAP_SUCCESS;
   long sec;
-  char *endp = NULL;
 
   slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
   
@@ -3350,11 +3332,11 @@ config_set_pw_warning( const char *attrname, char *value, char *errorbuf, int ap
   
   errno = 0;
   /* in seconds */
-  sec = strtol(value, &endp, 10);
+  sec = parse_duration(value);
 
-  if (*endp != '\0' || errno == ERANGE || sec < 0) {
+  if (errno == ERANGE || sec < 0) {
 	PR_snprintf ( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, 
-			   "%s: password warning age \"%s\" seconds is invalid, password warning "
+			   "%s: password warning age \"%s\" is invalid, password warning "
 			   "age must range from 0 to %ld seconds", 
 			   attrname, value, LONG_MAX );
 	retVal = LDAP_OPERATIONS_ERROR;

+ 2 - 4
ldap/servers/slapd/slapi-private.h

@@ -1117,10 +1117,10 @@ time_t read_localTime(struct berval* from);
 time_t parse_localTime(char* from);
 void write_localTime(time_t from, struct berval* into);
 time_t current_time( void );
-char* format_genTime(time_t from);
 void write_genTime(time_t from, struct berval* into);
 time_t read_genTime(struct berval* from);
-time_t parse_genTime(char* from);
+long parse_duration(char *value);
+char *gen_duration(long duration);
 
 /* Client SSL code */
 int slapd_security_library_is_initialized( void );
@@ -1226,8 +1226,6 @@ void    DS_Sleep(PRIntervalTime ticks);
 /* plugin.c */
 int plugin_enabled(const char *plugin_name, void *identity);
 
-int is_slapd_running();
-
 #ifdef __cplusplus
 }
 #endif

+ 84 - 1
ldap/servers/slapd/time.c

@@ -399,5 +399,88 @@ parse_genTime (char* from)
     tbv.bv_val = from;
     tbv.bv_len = strlen (from);
 
-	return read_genTime(&tbv);
+    return read_genTime(&tbv);
+}
+
+/*
+ * Return Value:
+ *   Success: duration in seconds
+ *   Failure: -1
+ */
+long
+parse_duration(char *value)
+{
+    char *input = NULL;
+    char *endp;
+    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;
+    }
+    if ('d' == *endp || 'D' == *endp) {
+        times = 60 * 60 * 24;
+        *endp = '\0';
+    } else if ('h' == *endp || 'H' == *endp) {
+        times = 60 * 60;
+        *endp = '\0';
+    } else if ('m' == *endp || 'M' == *endp) {
+        times = 60;
+        *endp = '\0';
+    } else if ('s' == *endp || 'S' == *endp) {
+        times = 1;
+        *endp = '\0';
+    }
+
+    duration = strtol(input, &endp, 10);
+    if ( *endp != '\0' || errno == ERANGE ) {
+        duration = -1;
+        goto bail;
+    }
+    duration *= times;
+
+bail:
+    slapi_ch_free_string(&input);
+    return duration;
+}
+
+/*
+ * caller is responsible to free the returned string
+ */
+char *
+gen_duration(long duration)
+{
+    char *duration_str = NULL;
+    long remainder = 0;
+    long devided = duration;
+    int devider[] = {60, 60, 24, 0};
+    char *unit[] = {"", "M", "H", "D", NULL};
+    int i = 0;
+
+    if (0 > duration) {
+        goto bail;
+    } else if (0 == duration) {
+        duration_str = strdup("0");
+        goto bail;
+    }
+    do { 
+        remainder = devided % devider[i];
+        if (remainder) {
+            break;
+        }
+        devided /= devider[i++];
+    } while (devider[i]);
+
+    duration_str = slapi_ch_smprintf("%ld%s", devided, unit[i]);
+
+bail:
+    return duration_str;
 }