From 1c3c56bec46a24b54acdd5fcbfd5fd00b8c0f95a Mon Sep 17 00:00:00 2001 From: Noriko Hosoi Date: Wed, 22 Jun 2016 17:38:08 -0700 Subject: [PATCH 1/2] Ticket #48896 - Default Setting for passwordMinTokenLength does not work Description: passwordMinTokenLength is supposed to be used for the length of comparison between the substring of obvious strings and a new password. But it was not used to generate substrings. This patch implements it. Also, old_pw was leaked in modify if password history was not enabled. --- ldap/servers/slapd/modify.c | 3 ++- ldap/servers/slapd/pw.c | 43 +++++++++++++++++++++++++++--------- ldap/servers/slapd/slapi-plugin.h | 4 ++++ ldap/servers/slapd/utf8.c | 46 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 11 deletions(-) diff --git a/ldap/servers/slapd/modify.c b/ldap/servers/slapd/modify.c index 4a5faa0..2665485 100644 --- a/ldap/servers/slapd/modify.c +++ b/ldap/servers/slapd/modify.c @@ -390,7 +390,8 @@ do_modify( Slapi_PBlock *pb ) ldap_mods_free (normalized_mods, 1 /* Free the Array and the Elements */); free_and_return:; - slapi_ch_free ((void**)&rawdn); + slapi_ch_free_string(&old_pw); + slapi_ch_free_string(&rawdn); slapi_mods_done(&smods); } diff --git a/ldap/servers/slapd/pw.c b/ldap/servers/slapd/pw.c index 498afd4..07ac089 100644 --- a/ldap/servers/slapd/pw.c +++ b/ldap/servers/slapd/pw.c @@ -621,7 +621,6 @@ update_pw_info ( Slapi_PBlock *pb , char *old_pw) /* update passwordHistory */ if ( old_pw != NULL && pwpolicy->pw_history == 1 ) { (void)update_pw_history(pb, sdn, old_pw); - slapi_ch_free ( (void**)&old_pw ); } /* Update the "pwdUpdateTime" attribute */ @@ -1046,9 +1045,13 @@ retry: * This is because password policy assumes that there's only one * password in the userpassword attribute. */ - *old_pw = slapi_ch_strdup(slapi_value_get_string(va[0])); + if (old_pw) { + *old_pw = slapi_ch_strdup(slapi_value_get_string(va[0])); + } } else { - *old_pw = NULL; + if (old_pw) { + *old_pw = NULL; + } } } } @@ -1535,13 +1538,13 @@ check_trivial_words (Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Value **vals, char { /* Add new value to valueset */ valp = slapi_value_new_berval( bvp ); - slapi_valueset_add_value_ext( vs, valp, SLAPI_VALUE_FLAG_PASSIN ); + slapi_valueset_add_value_ext( vs, valp, SLAPI_VALUE_FLAG_PASSIN ); valp = NULL; } } } /* Free smod */ - slapi_mod_free(&smod); + slapi_mod_free(&smod); smod = NULL; smodp = NULL; } @@ -1553,17 +1556,37 @@ check_trivial_words (Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Value **vals, char (i != -1) && (valp != NULL); i = slapi_valueset_next_value( vs, i, &valp) ) { + char *sp, *ep, *wp; + int found = 0; /* If the value is smaller than the max token length, * we don't need to check the password */ if ( ldap_utf8characters(slapi_value_get_string( valp )) < toklen ) continue; + sp = slapi_ch_strdup(slapi_value_get_string(valp)); + ep = sp + strlen(sp); + ep = ldap_utf8prevn(sp, ep, toklen); + if (!ep || (sp >= ep)) { + continue; + } /* See if the password contains the value */ - if ( PL_strcasestr( slapi_value_get_string( vals[0] ), - slapi_value_get_string( valp ) ) ) - { - if ( pwresponse_req == 1 ) - { + for (wp = sp; wp && (wp <= ep); wp = ldap_utf8next(wp)) { + char *tp = ldap_utf8nextn(wp, toklen); + char c; + if (tp) { + c = *tp; + *tp = '\0'; + } else { + break; + } + if (PL_strcasestr(slapi_value_get_string(vals[0]), wp)) { + found = 1; + } + *tp = c; + } + slapi_ch_free_string(&sp); + if (found) { + if ( pwresponse_req == 1 ) { slapi_pwpolicy_make_response_control ( pb, -1, -1, LDAP_PWPOLICY_INVALIDPWDSYNTAX ); } diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h index d3a6b25..ab40547 100644 --- a/ldap/servers/slapd/slapi-plugin.h +++ b/ldap/servers/slapd/slapi-plugin.h @@ -7448,6 +7448,10 @@ int ldap_utf8len( const char* ); char *ldap_utf8next( char* ); /* find previous character */ char *ldap_utf8prev( char* ); +/* find n-th character */ +char *ldap_utf8nextn (char* s, int n); +/* find n-th previous character from "from" */ +char *ldap_utf8prevn (char *s, char *from, int n); /* copy one character */ int ldap_utf8copy( char* dst, const char* src ); /* total number of characters */ diff --git a/ldap/servers/slapd/utf8.c b/ldap/servers/slapd/utf8.c index a1330ee..27843c0 100644 --- a/ldap/servers/slapd/utf8.c +++ b/ldap/servers/slapd/utf8.c @@ -93,6 +93,52 @@ ldap_utf8prev (char* s) return (char*) prev; } +/* + * Return a pointer to the n-th character following *s. + * Handle any valid UTF-8 character, including '\0' and ASCII. + * Try to handle a misaligned pointer or a malformed character. + * If the n-th character is beyond the string, it returns NULL. + */ +char* +ldap_utf8nextn (char* s, int n) +{ + char *endp; + char *next = s; + if (!s) { + return NULL; + } + endp = s + strlen(s); + for ( ;n > 0; --n) { + next = ldap_utf8next(next); + if ((next > endp) && (n > 0)) { + return NULL; + } + } + return next; +} + +/* + * Return a pointer to the n-th character preceding *from. + * Handle any valid UTF-8 character, including '\0' and ASCII. + * Try to handle a misaligned pointer or a malformed character. + * If the n-th previous character is beyond the start address, it returns NULL. + */ +char* +ldap_utf8prevn (char *s, char *from, int n) +{ + char *prev = from; + if (!s || !from || (s > from)) { + return NULL; + } + for ( ;n > 0; --n) { + prev = ldap_utf8prev(prev); + if ((prev <= s) && (n > 0)) { + return NULL; + } + } + return prev; +} + int ldap_utf8copy (char* dst, const char* src) /* Copy a character from src to dst; return the number of char's copied. -- 2.4.11