| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874 |
- /** BEGIN COPYRIGHT BLOCK
- * This Program is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License as published by the Free Software
- * Foundation; version 2 of the License.
- *
- * This Program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * In addition, as a special exception, Red Hat, Inc. gives You the additional
- * right to link the code of this Program with code not covered under the GNU
- * General Public License ("Non-GPL Code") and to distribute linked combinations
- * including the two, subject to the limitations in this paragraph. Non-GPL Code
- * permitted under this exception must only link to the code of this Program
- * through those well defined interfaces identified in the file named EXCEPTION
- * found in the source code files (the "Approved Interfaces"). The files of
- * Non-GPL Code may instantiate templates or use macros or inline functions from
- * the Approved Interfaces without causing the resulting work to be covered by
- * the GNU General Public License. Only Red Hat, Inc. may make changes or
- * additions to the list of Approved Interfaces. You must obey the GNU General
- * Public License in all respects for all of the Program code and other code used
- * in conjunction with the Program except the Non-GPL Code covered by this
- * exception. If you modify this file, you may extend this exception to your
- * version of the file, but you are not obligated to do so. If you do not wish to
- * provide this exception without modification, you must delete this exception
- * statement from your version and license this file solely under the GPL without
- * exception.
- *
- *
- * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
- * Copyright (C) 2005 Red Hat, Inc.
- * All rights reserved.
- * END COPYRIGHT BLOCK **/
- #ifdef HAVE_CONFIG_H
- # include <config.h>
- #endif
- /*
- * slapd hashed password routines
- *
- */
- #include <stdio.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sechash.h>
- #if defined( _WIN32 )
- #undef DEBUG
- #endif /* _WIN32 */
- #if defined( _WIN32 )
- #undef LDAPDebug
- #endif /* _WIN32 */
- #include "slap.h"
- #define DENY_PW_CHANGE_ACI "(targetattr = \"userPassword\") ( version 3.0; acl \"disallow_pw_change_aci\"; deny (write ) userdn = \"ldap:///self\";)"
- #define GENERALIZED_TIME_LENGTH 15
- static int pw_in_history(Slapi_Value **history_vals, const Slapi_Value *pw_val);
- static int update_pw_history( Slapi_PBlock *pb, char *dn, char *old_pw );
- static int check_trivial_words (Slapi_PBlock *, Slapi_Entry *, Slapi_Value **,
- char *attrtype, int toklen, Slapi_Mods *smods );
- static int pw_boolean_str2value (const char *str);
- /* static LDAPMod* pw_malloc_mod (char* name, char* value, int mod_op); */
- /*
- * We want to be able to return errors to internal operations (which
- * can come from the password change extended operation). So we have
- * a special result function that does the right thing for an internal op.
- */
- static void
- pw_send_ldap_result(
- Slapi_PBlock *pb,
- int err,
- char *matched,
- char *text,
- int nentries,
- struct berval **urls
- )
- {
- int internal_op = 0;
- Slapi_Operation *operation = NULL;
-
- slapi_pblock_get (pb, SLAPI_OPERATION, &operation);
- internal_op= operation_is_flag_set(operation, OP_FLAG_INTERNAL);
- if (internal_op) {
- slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_RESULT, &err);
- } else {
- send_ldap_result(pb, err, matched, text, nentries, urls);
- }
- }
- /*
- * Like slapi_value_find, except for passwords.
- * returns 0 if password "v" is found in "vals"; non-zero otherwise
- */
- SLAPI_DEPRECATED int
- slapi_pw_find(
- struct berval **vals,
- struct berval *v
- )
- {
- int rc;
- Slapi_Value **svin_vals= NULL;
- Slapi_Value svin_v;
- slapi_value_init_berval(&svin_v,v);
- valuearray_init_bervalarray(vals,&svin_vals); /* JCM SLOW FUNCTION */
- rc= slapi_pw_find_sv(svin_vals,&svin_v);
- valuearray_free(&svin_vals);
- value_done(&svin_v);
- return rc;
- }
- /*
- * Like slapi_value_find, except for passwords.
- * returns 0 if password "v" is found in "vals"; non-zero otherwise
- */
- int
- slapi_pw_find_sv(
- Slapi_Value **vals,
- const Slapi_Value *v
- )
- {
- struct pw_scheme *pwsp;
- char *valpwd;
- int i;
- LDAPDebug( LDAP_DEBUG_TRACE, "=> slapi_pw_find value: \"%s\"\n", slapi_value_get_string(v), 0, 0 ); /* JCM Innards */
- for ( i = 0; vals[i] != NULL; i++ )
- {
- pwsp = pw_val2scheme( (char*)slapi_value_get_string(vals[i]), &valpwd, 1 ); /* JCM Innards*/
- if ( pwsp != NULL &&
- (*(pwsp->pws_cmp))( (char*)slapi_value_get_string(v), valpwd ) == 0 ) /* JCM Innards*/
- {
- LDAPDebug( LDAP_DEBUG_TRACE,
- "<= slapi_pw_find matched \"%s\" using scheme \"%s\"\n",
- valpwd, pwsp->pws_name, 0 );
- free_pw_scheme( pwsp );
- return( 0 ); /* found it */
- }
- free_pw_scheme( pwsp );
- }
-
- LDAPDebug( LDAP_DEBUG_TRACE, "<= slapi_pw_find no matching password\n", 0, 0, 0 );
- return( 1 ); /* no match */
- }
- /* Checks if the specified value is encoded.
- Returns 1 if it is and 0 otherwise
- */
- int slapi_is_encoded (char *value)
- {
- struct pw_scheme *is_hashed = NULL;
- int is_encoded = 0;
- is_hashed = pw_val2scheme ( value, NULL, 0 );
- if ( is_hashed != NULL )
- {
- free_pw_scheme( is_hashed );
- is_encoded = 1;
- }
- return (is_encoded);
- }
- char* slapi_encode (char *value, char *alg)
- {
- struct pw_scheme *enc_scheme = NULL;
- char *hashedval = NULL;
- int need_to_free = 0;
- if (alg == NULL) /* use server encoding scheme */
- {
- slapdFrontendConfig_t * slapdFrontendConfig = getFrontendConfig();
-
- enc_scheme = slapdFrontendConfig->pw_storagescheme;
- if (enc_scheme == NULL)
- {
- slapi_log_error( SLAPI_LOG_FATAL, NULL,
- "slapi_encode: no server scheme\n" );
- return NULL;
- }
- }
- else
- {
- enc_scheme = pw_name2scheme(alg);
- if ( enc_scheme == NULL)
- {
- char * scheme_list = plugin_get_pwd_storage_scheme_list(PLUGIN_LIST_PWD_STORAGE_SCHEME);
- if ( scheme_list != NULL ) {
- slapi_log_error( SLAPI_LOG_FATAL, NULL,
- "slapi_encode: invalid scheme - %s\n"
- "Valid values are: %s\n", alg, scheme_list );
- slapi_ch_free((void **)&scheme_list);
- } else {
- slapi_log_error( SLAPI_LOG_FATAL, NULL,
- "slapi_encode: invalid scheme - %s\n"
- "no pwdstorage scheme plugin loaded", alg);
- }
- return NULL;
- }
- need_to_free = 1;
- }
-
- hashedval = enc_scheme->pws_enc(value);
- if (need_to_free)
- free_pw_scheme(enc_scheme);
- return hashedval;
- }
- /*
- * Return a pointer to the pw_scheme struct for scheme "name"
- * NULL is returned is no matching scheme is found.
- */
- struct pw_scheme *
- pw_name2scheme( char *name )
- {
- struct pw_scheme *pwsp;
- struct slapdplugin *p;
- if ( (p = plugin_get_pwd_storage_scheme(name, strlen(name), PLUGIN_LIST_PWD_STORAGE_SCHEME)) != NULL ) {
- pwsp = (struct pw_scheme *) slapi_ch_malloc (sizeof(struct pw_scheme));
- if ( pwsp != NULL ) {
- typedef int (*CMPFP)(char *, char *);
- typedef char * (*ENCFP)(char *);
- pwsp->pws_name = slapi_ch_strdup( p->plg_pwdstorageschemename );
- pwsp->pws_cmp = (CMPFP)p->plg_pwdstorageschemecmp;
- pwsp->pws_enc = (ENCFP)p->plg_pwdstorageschemeenc;
- pwsp->pws_len = strlen(pwsp->pws_name) ;
- return(pwsp);
- }
- }
- return( NULL );
- }
- void free_pw_scheme(struct pw_scheme *pwsp)
- {
- if ( pwsp != NULL )
- {
- slapi_ch_free( (void**)&pwsp->pws_name );
- slapi_ch_free( (void**)&pwsp );
- }
- }
- /*
- * Return the password scheme for value "val". This is determined by
- * checking "val" against our scheme prefixes.
- *
- * If "valpwdp" is not NULL, it is set to point to the value with any
- * prefix removed.
- *
- * If no matching scheme is found and first_is_default is non-zero, the
- * first scheme is returned. If no matching scheme is found and
- * first_is_default is zero, NULL is returned.
- */
- struct pw_scheme *
- pw_val2scheme( char *val, char **valpwdp, int first_is_default )
- {
- struct pw_scheme *pwsp;
- int namelen, prefixlen;
- char *end, buf[ PWD_MAX_NAME_LEN + 1 ];
- if ( *val != PWD_HASH_PREFIX_START ||
- ( end = strchr( val, PWD_HASH_PREFIX_END )) == NULL ||
- ( namelen = end - val - 1 ) > PWD_MAX_NAME_LEN ) {
- if ( !first_is_default ) {
- return( NULL );
- }
- pwsp = pw_name2scheme("CLEAR"); /* default to first scheme */
- prefixlen = 0;
- } else {
- memcpy( buf, val + 1, namelen );
- buf[ namelen ] = '\0';
- pwsp = pw_name2scheme(buf);
- if ( pwsp == NULL ) {
- if ( !first_is_default ) {
- return( NULL );
- }
- pwsp = pw_name2scheme("CLEAR");
- prefixlen = 0;
- } else {
- prefixlen = pwsp->pws_len + 2;
- }
- }
- if ( valpwdp != NULL ) {
- *valpwdp = val + prefixlen;
- }
- return( pwsp );
- }
- /*
- * re-encode the password values in "vals" using a hashing algorithm
- * vals[n] is assumed to be an alloc'd Slapi_Value that can be free'd and
- * replaced. If a value is already encoded, we do not re-encode it.
- * Return 0 if all goes well and < 0 if an error occurs.
- */
- int
- pw_encodevals( Slapi_Value **vals )
- {
- int i;
- slapdFrontendConfig_t * slapdFrontendConfig = getFrontendConfig();
- if ( vals == NULL || slapdFrontendConfig->pw_storagescheme == NULL ||
- slapdFrontendConfig->pw_storagescheme->pws_enc == NULL ) {
- return( 0 );
- }
- for ( i = 0; vals[ i ] != NULL; ++i ) {
- struct pw_scheme *pwsp;
- char *enc = NULL;
- if ( (pwsp=pw_val2scheme( (char*)slapi_value_get_string(vals[ i ]), NULL, 0)) != NULL ) { /* JCM Innards */
- /* If the value already specifies clear storage, call the
- * clear storage plug-in */
- if (strcasecmp( pwsp->pws_name, "clear" ) == 0) {
- enc = (*pwsp->pws_enc)( (char*)slapi_value_get_string(vals[ i ]) );
- } else {
- free_pw_scheme( pwsp );
- continue; /* don't touch pre-encoded values */
- }
- }
- if ((!enc) && (( enc = (*slapdFrontendConfig->pw_storagescheme->pws_enc)( (char*)slapi_value_get_string(vals[ i ]) )) /* JCM Innards */
- == NULL )) {
- free_pw_scheme( pwsp );
- return( -1 );
- }
- slapi_value_free(&vals[ i ]);
- vals[ i ] = slapi_value_new_string_passin(enc);
- free_pw_scheme( pwsp );
- }
- return( 0 );
- }
- /*
- * Check if the prefix of the cipher is the one that is supposed to be
- * Extract from the whole cipher the encrypted password (remove the prefix)
- */
- int checkPrefix(char *cipher, char *schemaName, char **encrypt)
- {
- int namelen;
- /* buf contains the extracted schema name */
- char *end, buf[ 3*PWD_MAX_NAME_LEN + 1 ];
- if ( (*cipher == PWD_HASH_PREFIX_START) &&
- ((end = strchr(cipher, PWD_HASH_PREFIX_END)) != NULL) &&
- ((namelen = end - cipher - 1 ) <= (3*PWD_MAX_NAME_LEN)) )
- {
- memcpy( buf, cipher + 1, namelen );
- buf[ namelen ] = '\0';
- if ( strcasecmp( buf, schemaName) != 0 )
- {
- /* schema names are different, error */
- return 1;
- }
- else
- {
- /* extract the encrypted password */
- *encrypt = cipher + strlen(schemaName) + 2;
- return 0;
- }
- }
- /* cipher is not prefixed, already in clear ? */
- return -1;
- }
- /*
- * Decode the attribute "attr_name" with one of the reversible encryption mechanism
- * Returns -1 on error
- * Returns 0 on success with strdup'ed plain
- * Returns 1 on success with *plain=cipher
- */
- int
- pw_rever_decode(char *cipher, char **plain, const char * attr_name)
- {
- struct pw_scheme *pwsp = NULL;
- struct slapdplugin *p = NULL;
- int ret_code = 1;
- for ( p = get_plugin_list(PLUGIN_LIST_REVER_PWD_STORAGE_SCHEME); p != NULL; p = p->plg_next )
- {
- char *L_attr = NULL;
- int i = 0;
- char *encrypt = NULL;
- int prefixOK = -1;
- /* Get the appropriate decoding function */
- for ( L_attr = p->plg_argv[i]; i<p->plg_argc; L_attr = p->plg_argv[++i] )
- {
- if (slapi_attr_types_equivalent(L_attr, attr_name))
- {
- typedef int (*CMPFP)(char *, char *);
- typedef char * (*ENCFP)(char *);
- pwsp = (struct pw_scheme *) slapi_ch_calloc (1, sizeof(struct pw_scheme));
- pwsp->pws_dec = (ENCFP)p->plg_pwdstorageschemedec;
- pwsp->pws_name = slapi_ch_strdup( p->plg_pwdstorageschemename );
- pwsp->pws_len = strlen(pwsp->pws_name) ;
- if ( pwsp->pws_dec != NULL )
- {
- /* check that the prefix of the cipher is the same name
- as the schema name */
- prefixOK = checkPrefix(cipher, pwsp->pws_name, &encrypt);
- if ( prefixOK == -1 )
- {
- /* no prefix, already in clear ? */
- *plain = cipher;
- ret_code = 1;
- goto free_and_return;
- }
- else if ( prefixOK == 1 )
- {
- /* schema names are different */
- ret_code = -1;
- goto free_and_return;
- }
- else
- {
- if ( ( *plain = (pwsp->pws_dec)( encrypt )) == NULL )
- {
- /* pb during decoding */
- ret_code = -1;
- goto free_and_return;
- }
- /* decoding is OK */
- ret_code = 0;
- goto free_and_return;
- }
- }
- free_pw_scheme( pwsp );
- pwsp = NULL;
- }
- }
- }
- free_and_return:
- if ( pwsp != NULL )
- {
- free_pw_scheme( pwsp );
- }
- return(ret_code);
- }
- /*
- * Encode the attribute "attr_name" with one of the reversible encryption mechanism
- */
- int
- pw_rever_encode(Slapi_Value **vals, char * attr_name)
- {
- char *enc;
- struct pw_scheme *pwsp = NULL;
- struct slapdplugin *p;
- if (vals == NULL){
- return (0);
- }
-
- for ( p = get_plugin_list(PLUGIN_LIST_REVER_PWD_STORAGE_SCHEME); p != NULL; p = p->plg_next )
- {
- char *L_attr = NULL;
- int i = 0;
- /* Get the appropriate encoding function */
- for ( L_attr = p->plg_argv[i]; i<p->plg_argc; L_attr = p->plg_argv[++i] )
- {
- if (slapi_attr_types_equivalent(L_attr, attr_name))
- {
- typedef int (*CMPFP)(char *, char *);
- typedef char * (*ENCFP)(char *);
- pwsp = (struct pw_scheme *) slapi_ch_calloc (1, sizeof(struct pw_scheme));
- pwsp->pws_enc = (ENCFP)p->plg_pwdstorageschemeenc;
- pwsp->pws_name = slapi_ch_strdup( p->plg_pwdstorageschemename );
- if ( pwsp->pws_enc != NULL )
- {
- for ( i = 0; vals[i] != NULL; ++i )
- {
- char *encrypt = NULL;
- int prefixOK;
- prefixOK = checkPrefix((char*)slapi_value_get_string(vals[i]),
- pwsp->pws_name,
- &encrypt);
- if ( prefixOK == 0 )
- {
- /* Don't touch already encoded value */
- continue; /* don't touch pre-encoded values */
- }
- else if (prefixOK == 1 )
- {
- /* credential is already encoded, but not with this schema. Error */
- free_pw_scheme( pwsp );
- return( -1 );
- }
-
- if ( ( enc = (pwsp->pws_enc)( (char*)slapi_value_get_string(vals[ i ]) )) == NULL )
- {
- free_pw_scheme( pwsp );
- return( -1 );
- }
- slapi_value_free(&vals[ i ]);
- vals[ i ] = slapi_value_new_string_passin(enc);
- free_pw_scheme( pwsp );
- return (0);
- }
- }
- }
- }
- }
-
- free_pw_scheme( pwsp );
- return(-1);
- }
- /* ONREPL - below are the functions moved from pw_mgmt.c.
- this is done to allow the functions to be used
- by functions linked into libslapd.
- */
- /* update_pw_info is called after password is modified successfully */
- /* it should update passwordHistory, and passwordExpirationTime */
- /* SLAPI_ENTRY_POST_OP must be set */
- int
- update_pw_info ( Slapi_PBlock *pb , char *old_pw) {
- Slapi_Mods smods;
- char *timestr;
- time_t pw_exp_date;
- time_t cur_time;
- char *dn;
- passwdPolicy *pwpolicy = NULL;
- cur_time = current_time();
- slapi_pblock_get( pb, SLAPI_TARGET_DN, &dn );
-
- pwpolicy = new_passwdPolicy(pb, dn);
- /* update passwordHistory */
- if ( old_pw != NULL && pwpolicy->pw_history == 1 ) {
- update_pw_history(pb, dn, old_pw);
- slapi_ch_free ( (void**)&old_pw );
- }
- slapi_mods_init(&smods, 0);
-
- /* update password allow change time */
- if ( pwpolicy->pw_minage != 0) {
- timestr = format_genTime( time_plus_sec( cur_time,
- pwpolicy->pw_minage ));
- slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordAllowChangeTime", timestr);
- slapi_ch_free((void **)×tr);
- }
- /* Fix for Bug 560707
- Removed the restriction that the lock variables (retry count) will
- be set only when root resets the passwd.
- Now admins will also have these privileges.
- */
- if (pwpolicy->pw_lockout) {
- set_retry_cnt_mods (pb, &smods, 0 );
- }
- /* Clear the passwordgraceusertime from the user entry */
- slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordgraceusertime", "0");
- /* if the password is reset by root, mark it the first time logon */
-
- if ( pb->pb_requestor_isroot == 1 &&
- pwpolicy->pw_must_change){
- pw_exp_date = NO_TIME;
- } else if ( pwpolicy->pw_exp == 1 ) {
- Slapi_Entry *pse = NULL;
- /* update password expiration date */
- pw_exp_date = time_plus_sec ( cur_time,
- pwpolicy->pw_maxage );
-
- slapi_pblock_get(pb,SLAPI_ENTRY_POST_OP,&pse);
- if (pse) {
- char *prev_exp_date_str;
-
- /* if the password expiry time is SLAPD_END_TIME,
- * don't roll it back
- */
- prev_exp_date_str = slapi_entry_attr_get_charptr(pse,"passwordExpirationTime");
-
- if (prev_exp_date_str) {
- time_t prev_exp_date;
- prev_exp_date = parse_genTime(prev_exp_date_str);
-
- if (prev_exp_date == NO_TIME ||
- prev_exp_date == NOT_FIRST_TIME) {
- /* ignore as will replace */
- } else if (prev_exp_date == SLAPD_END_TIME) {
- /* Special entries' passwords never expire */
- slapi_ch_free((void**)&prev_exp_date_str);
- pw_apply_mods(dn, &smods);
- slapi_mods_done(&smods);
- delete_passwdPolicy(&pwpolicy);
- return 0;
- }
-
- slapi_ch_free((void**)&prev_exp_date_str);
- }
- } /* post op entry */
- } else if (pwpolicy->pw_must_change) {
- /*
- * pw is not changed by root, and must change pw first time
- * log on
- */
- pw_exp_date = NOT_FIRST_TIME;
- } else {
- pw_apply_mods(dn, &smods);
- slapi_mods_done(&smods);
- delete_passwdPolicy(&pwpolicy);
- return 0;
- }
- delete_passwdPolicy(&pwpolicy);
- timestr = format_genTime ( pw_exp_date );
- slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordExpirationTime", timestr);
- slapi_ch_free((void **)×tr);
-
- slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordExpWarned", "0");
- pw_apply_mods(dn, &smods);
- slapi_mods_done(&smods);
- if (pb->pb_conn) { /* no conn for internal op */
- /* reset c_needpw to 0 */
- pb->pb_conn->c_needpw = 0;
- }
- return 0;
- }
- int
- check_pw_minage ( Slapi_PBlock *pb, const Slapi_DN *sdn, struct berval **vals)
- {
- char *dn= (char*)slapi_sdn_get_ndn(sdn); /* jcm - Had to cast away const */
- passwdPolicy *pwpolicy=NULL;
- int pwresponse_req = 0;
- pwpolicy = new_passwdPolicy(pb, dn);
- slapi_pblock_get ( pb, SLAPI_PWPOLICY, &pwresponse_req );
- if ( !pb->pb_op->o_isroot &&
- pwpolicy->pw_minage != 0 ) {
- Slapi_Entry *e;
- char *passwordAllowChangeTime;
- /* retrieve the entry */
- e = get_entry ( pb, dn );
- if ( e == NULL ) {
- delete_passwdPolicy(&pwpolicy);
- return ( -1 );
- }
- /* get passwordAllowChangeTime attribute */
- passwordAllowChangeTime= slapi_entry_attr_get_charptr(e, "passwordAllowChangeTime");
-
- if (passwordAllowChangeTime!=NULL)
- {
- time_t pw_allowchange_date;
- char *cur_time_str = NULL;
-
- pw_allowchange_date = parse_genTime(passwordAllowChangeTime);
- slapi_ch_free((void **) &passwordAllowChangeTime );
- /* check if allow to change the password */
- cur_time_str = format_genTime ( current_time() );
- if ( difftime ( pw_allowchange_date,
- parse_genTime ( cur_time_str )) > 0 )
- {
- if ( pwresponse_req == 1 ) {
- slapi_pwpolicy_make_response_control ( pb, -1, -1,
- LDAP_PWPOLICY_PWDTOOYOUNG );
- }
- pw_send_ldap_result ( pb,
- LDAP_CONSTRAINT_VIOLATION, NULL,
- "within password minimum age", 0, NULL );
- slapi_entry_free( e );
- slapi_ch_free((void **) &cur_time_str );
- delete_passwdPolicy(&pwpolicy);
- return ( 1 );
- }
- slapi_ch_free((void **) &cur_time_str );
- }
- slapi_entry_free( e );
- }
- delete_passwdPolicy(&pwpolicy);
- return ( 0 );
- }
- /* check_pw_syntax is called before add or modify operation on userpassword attribute*/
- int
- check_pw_syntax ( Slapi_PBlock *pb, const Slapi_DN *sdn, Slapi_Value **vals,
- char **old_pw, Slapi_Entry *e, int mod_op)
- {
- return ( check_pw_syntax_ext(pb, sdn, vals, old_pw, e, mod_op, NULL) );
- }
- int
- check_pw_syntax_ext ( Slapi_PBlock *pb, const Slapi_DN *sdn, Slapi_Value **vals,
- char **old_pw, Slapi_Entry *e, int mod_op, Slapi_Mods *smods)
- {
- Slapi_Attr* attr;
- int i, pwresponse_req = 0;
- char *dn= (char*)slapi_sdn_get_ndn(sdn); /* jcm - Had to cast away const */
- char *pwd = NULL;
- char *p = NULL;
- char errormsg[ BUFSIZ ];
- passwdPolicy *pwpolicy = NULL;
- pwpolicy = new_passwdPolicy(pb, dn);
- slapi_pblock_get ( pb, SLAPI_PWPOLICY, &pwresponse_req );
- if ( pwpolicy->pw_syntax == 1 ) {
- for ( i = 0; vals[ i ] != NULL; ++i ) {
- int syntax_violation = 0;
- int num_digits = 0;
- int num_alphas = 0;
- int num_uppers = 0;
- int num_lowers = 0;
- int num_specials = 0;
- int num_8bit = 0;
- int num_repeated = 0;
- int max_repeated = 0;
- int num_categories = 0;
- /* check for the minimum password length */
- if ( pwpolicy->pw_minlength >
- ldap_utf8characters((char *)slapi_value_get_string( vals[i] )) )
- {
- PR_snprintf( errormsg, BUFSIZ,
- "invalid password syntax - password must be at least %d characters long",
- pwpolicy->pw_minlength );
- if ( pwresponse_req == 1 ) {
- slapi_pwpolicy_make_response_control ( pb, -1, -1,
- LDAP_PWPOLICY_PWDTOOSHORT );
- }
- pw_send_ldap_result ( pb, LDAP_CONSTRAINT_VIOLATION, NULL, errormsg, 0, NULL );
- delete_passwdPolicy(&pwpolicy);
- return ( 1 );
- }
- /* check character types */
- pwd = (char *)slapi_value_get_string( vals[i] );
- p = pwd;
- while ( p && *p )
- {
- if ( ldap_utf8isdigit( p ) ) {
- num_digits++;
- } else if ( ldap_utf8isalpha( p ) ) {
- num_alphas++;
- if ( slapi_utf8isLower( (unsigned char *)p ) ) {
- num_lowers++;
- } else {
- num_uppers++;
- }
- } else {
- /* check if this is an 8-bit char */
- if ( *p & 128 ) {
- num_8bit++;
- } else {
- num_specials++;
- }
- }
- /* check for repeating characters. If this is the
- first char of the password, no need to check */
- if ( pwd != p ) {
- int len = ldap_utf8len( p );
- char *prev_p = ldap_utf8prev( p );
- if ( len == ldap_utf8len( prev_p ) )
- {
- if ( memcmp( p, prev_p, len ) == 0 )
- {
- num_repeated++;
- if ( max_repeated < num_repeated ) {
- max_repeated = num_repeated;
- }
- } else {
- num_repeated = 0;
- }
- } else {
- num_repeated = 0;
- }
- }
- p = ldap_utf8next( p );
- }
- /* tally up the number of character categories */
- if ( num_digits > 0 )
- ++num_categories;
- if ( num_uppers > 0 )
- ++num_categories;
- if ( num_lowers > 0 )
- ++num_categories;
- if ( num_specials > 0 )
- ++num_categories;
- if ( num_8bit > 0 )
- ++num_categories;
- /* check for character based syntax limits */
- if ( pwpolicy->pw_mindigits > num_digits ) {
- syntax_violation = 1;
- PR_snprintf ( errormsg, BUFSIZ,
- "invalid password syntax - password must contain at least %d digit characters",
- pwpolicy->pw_mindigits );
- } else if ( pwpolicy->pw_minalphas > num_alphas ) {
- syntax_violation = 1;
- PR_snprintf ( errormsg, BUFSIZ,
- "invalid password syntax - password must contain at least %d alphabetic characters",
- pwpolicy->pw_minalphas );
- } else if ( pwpolicy->pw_minuppers > num_uppers ) {
- syntax_violation = 1;
- PR_snprintf ( errormsg, BUFSIZ,
- "invalid password syntax - password must contain at least %d uppercase characters",
- pwpolicy->pw_minuppers );
- } else if ( pwpolicy->pw_minlowers > num_lowers ) {
- syntax_violation = 1;
- PR_snprintf ( errormsg, BUFSIZ,
- "invalid password syntax - password must contain at least %d lowercase characters",
- pwpolicy->pw_minlowers );
- } else if ( pwpolicy->pw_minspecials > num_specials ) {
- syntax_violation = 1;
- PR_snprintf ( errormsg, BUFSIZ,
- "invalid password syntax - password must contain at least %d special characters",
- pwpolicy->pw_minspecials );
- } else if ( pwpolicy->pw_min8bit > num_8bit ) {
- syntax_violation = 1;
- PR_snprintf ( errormsg, BUFSIZ,
- "invalid password syntax - password must contain at least %d 8-bit characters",
- pwpolicy->pw_min8bit );
- } else if ( (pwpolicy->pw_maxrepeats != 0) && (pwpolicy->pw_maxrepeats < (max_repeated + 1)) ) {
- syntax_violation = 1;
- PR_snprintf ( errormsg, BUFSIZ,
- "invalid password syntax - a character cannot be repeated more than %d times",
- (pwpolicy->pw_maxrepeats + 1) );
- } else if ( pwpolicy->pw_mincategories > num_categories ) {
- syntax_violation = 1;
- PR_snprintf ( errormsg, BUFSIZ,
- "invalid password syntax - password must contain at least %d character "
- "categories (valid categories are digit, uppercase, lowercase, special, and 8-bit characters)",
- pwpolicy->pw_mincategories );
- }
- /* If the password failed syntax checking, send the result and return */
- if (syntax_violation) {
- if ( pwresponse_req == 1 ) {
- slapi_pwpolicy_make_response_control ( pb, -1, -1,
- LDAP_PWPOLICY_INVALIDPWDSYNTAX );
- }
- pw_send_ldap_result ( pb, LDAP_CONSTRAINT_VIOLATION, NULL, errormsg, 0, NULL );
- delete_passwdPolicy(&pwpolicy);
- return ( 1 );
- }
- }
- }
- /* get the entry and check for the password history if this is called by a modify operation */
- if ( mod_op ) {
- /* retrieve the entry */
- e = get_entry ( pb, dn );
- if ( e == NULL ) {
- delete_passwdPolicy(&pwpolicy);
- return ( -1 );
- }
- /* check for password history */
- if ( pwpolicy->pw_history == 1 ) {
- attr = attrlist_find(e->e_attrs, "passwordHistory");
- if (attr &&
- !valueset_isempty(&attr->a_present_values))
- {
- Slapi_Value **va= attr_get_present_values(attr);
- if ( pw_in_history( va, vals[0] ) == 0 ) {
- if ( pwresponse_req == 1 ) {
- slapi_pwpolicy_make_response_control ( pb, -1, -1,
- LDAP_PWPOLICY_PWDINHISTORY );
- }
- pw_send_ldap_result ( pb,
- LDAP_CONSTRAINT_VIOLATION, NULL,
- "password in history", 0, NULL );
- slapi_entry_free( e );
- delete_passwdPolicy(&pwpolicy);
- return ( 1 );
- }
- }
- /* get current password. check it and remember it */
- attr = attrlist_find(e->e_attrs, "userpassword");
- if (attr && !valueset_isempty(&attr->a_present_values))
- {
- Slapi_Value **va= valueset_get_valuearray(&attr->a_present_values);
- if (slapi_is_encoded((char*)slapi_value_get_string(vals[0])))
- {
- if (slapi_attr_value_find(attr, (struct berval *)slapi_value_get_berval(vals[0])) == 0 )
- {
- pw_send_ldap_result ( pb,
- LDAP_CONSTRAINT_VIOLATION ,NULL,
- "password in history", 0, NULL);
- slapi_entry_free( e );
- delete_passwdPolicy(&pwpolicy);
- return ( 1 );
- }
- } else
- {
- if ( slapi_pw_find_sv ( va, vals[0] ) == 0 )
- {
- pw_send_ldap_result ( pb,
- LDAP_CONSTRAINT_VIOLATION ,NULL,
- "password in history", 0, NULL);
- slapi_entry_free( e );
- delete_passwdPolicy(&pwpolicy);
- return ( 1 );
- }
- }
- /* We copy the 1st value of the userpassword attribute.
- * 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]));
- } else {
- *old_pw = NULL;
- }
- }
- }
- /* check for trivial words if syntax checking is enabled */
- if ( pwpolicy->pw_syntax == 1 ) {
- /* e is null if this is an add operation*/
- if ( check_trivial_words ( pb, e, vals, "uid", pwpolicy->pw_mintokenlength, smods ) == 1 ||
- check_trivial_words ( pb, e, vals, "cn", pwpolicy->pw_mintokenlength, smods ) == 1 ||
- check_trivial_words ( pb, e, vals, "sn", pwpolicy->pw_mintokenlength, smods ) == 1 ||
- check_trivial_words ( pb, e, vals, "givenname", pwpolicy->pw_mintokenlength, smods ) == 1 ||
- check_trivial_words ( pb, e, vals, "ou", pwpolicy->pw_mintokenlength, smods ) == 1 ||
- check_trivial_words ( pb, e, vals, "mail", pwpolicy->pw_mintokenlength, smods ) == 1)
- {
- if ( mod_op ) {
- slapi_entry_free( e );
- }
- delete_passwdPolicy(&pwpolicy);
- return 1;
- }
- }
- delete_passwdPolicy(&pwpolicy);
- if ( mod_op ) {
- /* free e only when called by modify operation */
- slapi_entry_free( e );
- }
- return 0; /* success */
- }
- static
- int update_pw_history( Slapi_PBlock *pb, char *dn, char *old_pw ) {
- time_t t, old_t, cur_time;
- int i = 0, oldest = 0;
- int res;
- Slapi_Entry *e;
- Slapi_Attr *attr;
- LDAPMod attribute;
- char *values_replace[25]; /* 2-24 passwords in history */
- LDAPMod *list_of_mods[2];
- Slapi_PBlock mod_pb;
- char *history_str;
- char *str;
- passwdPolicy *pwpolicy = NULL;
- pwpolicy = new_passwdPolicy(pb, dn);
- /* retrieve the entry */
- e = get_entry ( pb, dn );
- if ( e == NULL ) {
- delete_passwdPolicy(&pwpolicy);
- return ( 1 );
- }
- history_str = (char *)slapi_ch_malloc(GENERALIZED_TIME_LENGTH + strlen(old_pw) + 1);
- /* get password history, and find the oldest password in history */
- cur_time = current_time ();
- old_t = cur_time;
- str = format_genTime ( cur_time );
- attr = attrlist_find(e->e_attrs, "passwordHistory");
- if (attr && !valueset_isempty(&attr->a_present_values))
- {
- Slapi_Value **va= valueset_get_valuearray(&attr->a_present_values);
- for ( i = oldest = 0 ;
- (va[i] != NULL) && (slapi_value_get_length(va[i]) > 0) ;
- i++ ) {
- values_replace[i] = (char*)slapi_value_get_string(va[i]);
- strncpy( history_str, values_replace[i], GENERALIZED_TIME_LENGTH);
- history_str[GENERALIZED_TIME_LENGTH] = '\0';
- if (history_str[GENERALIZED_TIME_LENGTH - 1] != 'Z'){
- /* The time is not a generalized Time. Probably a password history from 4.x */
- history_str[GENERALIZED_TIME_LENGTH - 1] = '\0';
- }
- t = parse_genTime ( history_str );
- if ( difftime ( t, old_t ) < 0 ) {
- oldest = i;
- old_t = t;
- }
- }
- }
- strcpy ( history_str, str );
- strcat ( history_str, old_pw );
- if ( i == pwpolicy->pw_inhistory ) {
- /* replace the oldest password in history */
- values_replace [oldest] = history_str;
- values_replace[i]=NULL;
- } else {
- /* add old_pw at the end of password history */
- values_replace[i] = history_str;
- values_replace[++i]=NULL;
- }
- /* modify the attribute */
- attribute.mod_type = "passwordHistory";
- attribute.mod_op = LDAP_MOD_REPLACE;
- attribute.mod_values = values_replace;
-
- list_of_mods[0] = &attribute;
- list_of_mods[1] = NULL;
- pblock_init(&mod_pb);
- slapi_modify_internal_set_pb(&mod_pb, dn, list_of_mods, NULL, NULL,
- pw_get_componentID(), 0);
- slapi_modify_internal_pb(&mod_pb);
- slapi_pblock_get(&mod_pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
- if (res != LDAP_SUCCESS){
- LDAPDebug(LDAP_DEBUG_ANY, "WARNING: passwordPolicy modify error %d on entry '%s'\n",
- res, dn, 0);
- }
- pblock_done(&mod_pb);
- slapi_ch_free((void **) &str );
- slapi_ch_free((void **) &history_str );
- slapi_entry_free( e );
- delete_passwdPolicy(&pwpolicy);
- return 0;
- }
- static
- int pw_in_history( Slapi_Value **history_vals, const Slapi_Value *pw_val)
- {
- Slapi_Value *history[25];
- Slapi_Value historycv[25];
- int i;
- int ret = -1;
- const char *pw_str = slapi_value_get_string(pw_val);
-
- if (slapi_is_encoded((char*)pw_str)){
- /* If the password is encoded, we just do a string match with all previous passwords */
- for ( i = 0; history_vals[i] != NULL; i++){
- const char * h_val = slapi_value_get_string(history_vals[i]);
-
- if ( h_val != NULL &&
- slapi_value_get_length(history_vals[i]) >= 14 )
- {
- int pos = 14;
- if (h_val[pos] == 'Z')
- pos++;
- if (strcmp(&(h_val[pos]), pw_str) == 0){
- /* Password found */
- /* Let's just return */
- return (0);
- }
- }
- }
- }
- else { /* Password is in clear */
- /* strip the timestamps */
- for ( i = 0; history_vals[i] != NULL; i++ )
- {
- char *h_val = (char *)slapi_value_get_string(history_vals[i]);
- size_t h_len = slapi_value_get_length(history_vals[i]);
-
- historycv[i].v_csnset = NULL; /* JCM - I don't understand this */
- history[i] = &historycv[i];
- if ( h_val != NULL &&
- h_len >= 14 )
- {
- /* LP: With the new genTime, the password history format has changed */
- int pos = 14;
- if (h_val[pos] == 'Z')
- pos++;
- historycv[i].bv.bv_val = &(h_val[pos]);
- historycv[i].bv.bv_len = h_len - pos;
- } else {
- historycv[i].bv.bv_val = NULL;
- historycv[i].bv.bv_len = 0;
- }
- }
- history[i] = NULL;
- ret = slapi_pw_find_sv( history, pw_val);
- }
-
- return ( ret );
- }
- int
- slapi_add_pwd_control ( Slapi_PBlock *pb, char *arg, long time) {
- LDAPControl new_ctrl;
- char buf[12];
-
- LDAPDebug( LDAP_DEBUG_TRACE, "=> slapi_add_pwd_control\n", 0, 0, 0 );
-
- sprintf( buf, "%ld", time );
- new_ctrl.ldctl_oid = arg;
- new_ctrl.ldctl_value.bv_val = buf;
- new_ctrl.ldctl_value.bv_len = strlen( buf );
- new_ctrl.ldctl_iscritical = 0; /* 0 = false. */
-
- if ( slapi_pblock_set( pb, SLAPI_ADD_RESCONTROL, &new_ctrl ) != 0 ) {
- return( -1 );
- }
- return( 0 );
- }
- void
- pw_mod_allowchange_aci(int pw_prohibit_change) {
- const Slapi_DN *base;
- char *values_mod[2];
- LDAPMod mod;
- LDAPMod *mods[2];
- Slapi_Backend *be;
- char *cookie = NULL;
- mods[0] = &mod;
- mods[1] = NULL;
- mod.mod_type = "aci";
- mod.mod_values = values_mod;
- if (pw_prohibit_change) {
- mod.mod_op = LDAP_MOD_ADD;
- }
- else
- {
- /* Allow change password by default */
- /* remove the aci if it is there. it is ok to fail */
- mod.mod_op = LDAP_MOD_DELETE;
- }
- be = slapi_get_first_backend (&cookie);
- /* Foreach backend... */
- while (be)
- {
- /* Don't add aci on a chaining backend holding remote entries */
- if((!be->be_private) && (!slapi_be_is_flag_set(be,SLAPI_BE_FLAG_REMOTE_DATA)))
- {
- /* There's only One suffix per DB now. No need to loop */
- base = slapi_be_getsuffix(be, 0);
- if (base != NULL)
- {
- Slapi_PBlock pb;
- int rc;
-
- pblock_init (&pb);
- values_mod[0] = DENY_PW_CHANGE_ACI;
- values_mod[1] = NULL;
- slapi_modify_internal_set_pb(&pb, slapi_sdn_get_dn(base), mods, NULL, NULL, pw_get_componentID(), 0);
- slapi_modify_internal_pb(&pb);
- slapi_pblock_get(&pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
- if (rc == LDAP_SUCCESS){
- /*
- ** Since we modified the acl
- ** successfully, let's update the
- ** in-memory acl list
- */
- slapi_pblock_set(&pb, SLAPI_TARGET_DN, (char*)slapi_sdn_get_dn(base) ); /* jcm: cast away const */
- plugin_call_acl_mods_update (&pb, LDAP_REQ_MODIFY );
- }
- pblock_done(&pb);
- }
- }
- be = slapi_get_next_backend (cookie);
- }
- slapi_ch_free((void **) &cookie);
- }
- void
- add_password_attrs( Slapi_PBlock *pb, Operation *op, Slapi_Entry *e )
- {
- struct berval bv;
- struct berval *bvals[2];
- Slapi_Attr **a, **next;
- passwdPolicy *pwpolicy = NULL;
- char *dn = slapi_entry_get_ndn(e);
- pwpolicy = new_passwdPolicy(pb, dn);
- 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;
- }
- next = &(*a)->a_next;
- }
- bv.bv_val = format_genTime ( time_plus_sec ( current_time (),
- pwpolicy->pw_maxage ) );
- }
- if ( pwpolicy->pw_exp || pwpolicy->pw_must_change ) {
- bv.bv_len = strlen( bv.bv_val );
- slapi_entry_attr_merge( e, "passwordexpirationtime", bvals );
- }
- 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 ( pwpolicy->pw_minage != 0 ) {
- bv.bv_val = format_genTime ( time_plus_sec ( current_time (),
- pwpolicy->pw_minage ) );
- bv.bv_len = strlen( bv.bv_val );
-
- slapi_entry_attr_merge( e, "passwordallowchangetime", bvals );
- slapi_ch_free((void **) &bv.bv_val );
- }
-
- delete_passwdPolicy(&pwpolicy);
- }
- static int
- check_trivial_words (Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Value **vals, char *attrtype,
- int toklen, Slapi_Mods *smods )
- {
- Slapi_Attr *attr = NULL;
- Slapi_Mod *smodp = NULL, *smod = NULL;
- Slapi_ValueSet *vs = NULL;
- Slapi_Value *valp = NULL;
- struct berval *bvp = NULL;
- int i, pwresponse_req = 0;
- slapi_pblock_get ( pb, SLAPI_PWPOLICY, &pwresponse_req );
- /* Get a list of present values for attrtype in the existing entry, if there is one */
- if (e != NULL )
- {
- if ( (attr = attrlist_find(e->e_attrs, attrtype)) &&
- (!valueset_isempty(&attr->a_present_values)) )
- {
- /* allocate and add present values to valueset */
- slapi_attr_get_valueset( attr, &vs );
- }
- }
- /* allocate new one if not allocated above by
- slapi_attr_get_valueset */
- if (!vs) {
- vs = slapi_valueset_new();
- }
- /* Get a list of new values for attrtype from the operation */
- if ( (smod = slapi_mod_new()) && smods )
- {
- for (smodp = slapi_mods_get_first_smod(smods, smod);
- smodp != NULL; smodp = slapi_mods_get_next_smod(smods, smod) )
- {
- /* Operation has new values for attrtype */
- if ( PL_strcasecmp(attrtype, slapi_mod_get_type(smodp)) == 0 )
- {
- /* iterate through smodp values and add them if they don't exist */
- for ( bvp = slapi_mod_get_first_value( smodp ); bvp != NULL;
- bvp = slapi_mod_get_next_value( smodp ) )
- {
- /* Add new value to valueset */
- valp = slapi_value_new_berval( bvp );
- slapi_valueset_add_value_ext( vs, valp, SLAPI_VALUE_FLAG_PASSIN );
- valp = NULL;
- }
- }
- }
- /* Free smod */
- slapi_mod_free(&smod);
- smod = NULL;
- smodp = NULL;
- }
- /* If valueset isn't empty, we need to check if the password contains the values */
- if ( slapi_valueset_count(vs) != 0 )
- {
- for ( i = slapi_valueset_first_value( vs, &valp);
- (i != -1) && (valp != NULL);
- i = slapi_valueset_next_value( vs, i, &valp) )
- {
- /* 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;
- /* 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 )
- {
- slapi_pwpolicy_make_response_control ( pb, -1, -1,
- LDAP_PWPOLICY_INVALIDPWDSYNTAX );
- }
- pw_send_ldap_result ( pb,
- LDAP_CONSTRAINT_VIOLATION, NULL,
- "invalid password syntax - password based off of user entry", 0, NULL );
- /* Free valueset */
- slapi_valueset_free( vs );
- return ( 1 );
- }
- }
- }
- /* Free valueset */
- slapi_valueset_free( vs );
- return ( 0 );
- }
- void
- pw_add_allowchange_aci(Slapi_Entry *e, int pw_prohibit_change) {
- char *aci_pw = NULL;
- const char *aciattr = "aci";
- aci_pw = slapi_ch_strdup(DENY_PW_CHANGE_ACI);
- if (pw_prohibit_change) {
- /* Add ACI */
- slapi_entry_add_string(e, aciattr, aci_pw);
- } else {
- /* Remove ACI */
- slapi_entry_delete_string(e, aciattr, aci_pw);
- }
- slapi_ch_free((void **) &aci_pw);
- }
- /* This function creates a passwdPolicy structure, loads it from either
- * slapdFrontendconfig or the entry pointed by pwdpolicysubentry and
- * returns the structure.
- */
- passwdPolicy *
- new_passwdPolicy(Slapi_PBlock *pb, char *dn)
- {
- Slapi_ValueSet *values = NULL;
- Slapi_Entry *e = NULL, *pw_entry = NULL;
- int type_name_disposition = 0;
- char *actual_type_name = NULL;
- int attr_free_flags = 0;
- int rc=0;
- passwdPolicy *pwdpolicy = NULL;
- Slapi_Attr *attr;
- char *attr_name;
- Slapi_Value **sval;
- slapdFrontendConfig_t *slapdFrontendConfig;
- Slapi_Operation *op;
- char ebuf[ BUFSIZ ];
- int optype = -1;
- slapdFrontendConfig = getFrontendConfig();
- pwdpolicy = (passwdPolicy *)slapi_ch_calloc(1, sizeof(passwdPolicy));
- slapi_pblock_get( pb, SLAPI_OPERATION, &op);
- slapi_pblock_get( pb, SLAPI_OPERATION_TYPE, &optype );
- if (slapdFrontendConfig->pwpolicy_local == 1) {
- if ( !operation_is_flag_set( op, OP_FLAG_INTERNAL ) && dn ) {
- /* If we're doing an add, COS does not apply yet so we check
- parents for the pwdpolicysubentry. We look only for virtual
- attributes, because real ones are for single-target policy. */
- if (optype == SLAPI_OPERATION_ADD) {
- char *parentdn = slapi_ch_strdup(dn);
- char *nextdn = NULL;
- while ((nextdn = slapi_dn_parent( parentdn )) != NULL) {
- if (((e = get_entry( pb, nextdn )) != NULL)) {
- if ((slapi_vattr_values_get(e, "pwdpolicysubentry",
- &values, &type_name_disposition, &actual_type_name,
- SLAPI_VIRTUALATTRS_REQUEST_POINTERS |
- SLAPI_VIRTUALATTRS_ONLY,
- &attr_free_flags)) == 0) {
- /* pwdpolicysubentry found! */
- break;
- } else {
- /* Parent didn't have it, check grandparent... */
- slapi_ch_free_string( &parentdn );
- parentdn = nextdn;
- slapi_entry_free( e );
- e = NULL;
- }
- } else {
- /* Reached the top without finding a pwdpolicysubentry. */
- break;
- }
- }
- slapi_ch_free_string( &parentdn );
- slapi_ch_free_string( &nextdn );
- /* If we're not doing an add, we look for the pwdpolicysubentry
- attribute in the target entry itself. */
- } else {
- if ( (e = get_entry( pb, dn )) != NULL ) {
- rc = slapi_vattr_values_get(e, "pwdpolicysubentry", &values,
- &type_name_disposition, &actual_type_name,
- SLAPI_VIRTUALATTRS_REQUEST_POINTERS, &attr_free_flags);
- if (rc) {
- values = NULL;
- }
- }
- }
- if (values != NULL) {
- Slapi_Value *v = NULL;
- const struct berval *bvp = NULL;
- if ( ((rc = slapi_valueset_first_value( values, &v )) != -1) &&
- ( bvp = slapi_value_get_berval( v )) != NULL ) {
- if ( bvp != NULL ) {
- /* we got the pwdpolicysubentry value */
- pw_entry = get_entry ( pb, bvp->bv_val);
- }
- }
- slapi_vattr_values_free(&values, &actual_type_name, attr_free_flags);
- slapi_entry_free( e );
- if ( pw_entry == NULL ) {
- LDAPDebug(LDAP_DEBUG_ANY, "loading global password policy for %s"
- "--local policy entry not found\n", escape_string(dn, ebuf),0,0);
- goto done;
- }
-
- for (slapi_entry_first_attr(pw_entry, &attr); attr;
- slapi_entry_next_attr(pw_entry, attr, &attr))
- {
- 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_long(*sval);
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordmaxage")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_maxage = slapi_value_get_long(*sval);
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordwarning")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_warning = slapi_value_get_long(*sval);
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordhistory")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_history =
- pw_boolean_str2value(slapi_value_get_string(*sval));
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordinhistory")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_inhistory = slapi_value_get_int(*sval);
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordlockout")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_lockout =
- pw_boolean_str2value(slapi_value_get_string(*sval));
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordmaxfailure")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_maxfailure = slapi_value_get_int(*sval);
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordunlock")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_unlock =
- pw_boolean_str2value(slapi_value_get_string(*sval));
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordlockoutduration")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_lockduration = slapi_value_get_long(*sval);
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordresetfailurecount")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_resetfailurecount = slapi_value_get_long(*sval);
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordchange")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_change =
- pw_boolean_str2value(slapi_value_get_string(*sval));
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordmustchange")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_must_change =
- pw_boolean_str2value(slapi_value_get_string(*sval));
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordchecksyntax")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_syntax =
- pw_boolean_str2value(slapi_value_get_string(*sval));
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordminlength")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_minlength = slapi_value_get_int(*sval);
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordmindigits")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_mindigits = slapi_value_get_int(*sval);
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordminalphas")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_minalphas = slapi_value_get_int(*sval);
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordminuppers")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_minuppers = slapi_value_get_int(*sval);
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordminlowers")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_minlowers = slapi_value_get_int(*sval);
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordminspecials")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_minspecials = slapi_value_get_int(*sval);
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordmin8bit")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_min8bit = slapi_value_get_int(*sval);
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordmaxrepeats")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_maxrepeats = slapi_value_get_int(*sval);
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordmincategories")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_mincategories = slapi_value_get_int(*sval);
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordmintokenlength")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_mintokenlength = slapi_value_get_int(*sval);
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordexp")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_exp =
- pw_boolean_str2value(slapi_value_get_string(*sval));
- }
- }
- else
- if (!strcasecmp(attr_name, "passwordgracelimit")) {
- if ((sval = attr_get_present_values(attr))) {
- pwdpolicy->pw_gracelimit = slapi_value_get_int(*sval);
- }
- }
-
- } /* end of for() loop */
- if (pw_entry) {
- slapi_entry_free(pw_entry);
- }
- return pwdpolicy;
- } else if ( e ) {
- slapi_entry_free( e );
- }
- }
- }
- done:
- /* If we are here, that means we need to load the passwdPolicy
- * structure from slapdFrontendconfig
- */
- *pwdpolicy = slapdFrontendConfig->pw_policy;
- return pwdpolicy;
- } /* End of new_passwdPolicy() */
- void
- delete_passwdPolicy( passwdPolicy **pwpolicy)
- {
- slapi_ch_free((void **)pwpolicy);
- }
- /*
- * Encode the PWPOLICY RESPONSE control.
- *
- * Create a password policy response control,
- * and add it to the PBlock to be returned to the client.
- *
- * Returns:
- * success ( 0 )
- * operationsError (1),
- */
- int
- slapi_pwpolicy_make_response_control (Slapi_PBlock *pb, int seconds, int logins, ber_int_t error)
- {
- BerElement *ber= NULL;
- struct berval *bvp = NULL;
- int rc = -1;
- /*
- PasswordPolicyResponseValue ::= SEQUENCE {
- warning [0] CHOICE OPTIONAL {
- timeBeforeExpiration [0] INTEGER (0 .. maxInt),
- graceLoginsRemaining [1] INTEGER (0 .. maxInt) }
- error [1] ENUMERATED OPTIONAL {
- passwordExpired (0),
- accountLocked (1),
- changeAfterReset (2),
- passwordModNotAllowed (3),
- mustSupplyOldPassword (4),
- invalidPasswordSyntax (5),
- passwordTooShort (6),
- passwordTooYoung (7),
- passwordInHistory (8) } }
- */
-
- LDAPDebug( LDAP_DEBUG_TRACE, "=> slapi_pwpolicy_make_response_control", 0, 0, 0 );
- if ( ( ber = ber_alloc()) == NULL )
- {
- return rc;
- }
- rc = ber_printf( ber, "{" );
- if ( seconds >= 0 || logins >= 0 ) {
- if ( seconds >= 0 ) {
- rc = ber_printf( ber, "t{ti}", LDAP_TAG_PWP_WARNING,
- LDAP_TAG_PWP_SECSLEFT,
- seconds );
- }
- else {
- rc = ber_printf( ber, "t{ti}", LDAP_TAG_PWP_WARNING,
- LDAP_TAG_PWP_GRCLOGINS,
- logins );
- }
- }
- if ( error >= 0 ) {
- rc = ber_printf( ber, "te", LDAP_TAG_PWP_ERROR, error );
- }
- rc = ber_printf( ber, "}" );
- if ( rc != -1 )
- {
- rc = ber_flatten( ber, &bvp );
- }
-
- ber_free( ber, 1 );
- if ( rc != -1 )
- {
- LDAPControl new_ctrl = {0};
- new_ctrl.ldctl_oid = LDAP_X_CONTROL_PWPOLICY_RESPONSE;
- new_ctrl.ldctl_value = *bvp;
- new_ctrl.ldctl_iscritical = 0;
- rc= slapi_pblock_set( pb, SLAPI_ADD_RESCONTROL, &new_ctrl );
- ber_bvfree(bvp);
- }
- LDAPDebug( LDAP_DEBUG_TRACE, "<= slapi_pwpolicy_make_response_control", 0, 0, 0 );
- return (rc==-1?LDAP_OPERATIONS_ERROR:LDAP_SUCCESS);
- }
- static int
- pw_boolean_str2value (const char *str)
- {
- if ( !strcasecmp(str, "true") ||
- !strcasecmp(str, "on") ||
- !strcasecmp(str, "1") ) {
- return ( LDAP_ON );
- }
- if ( !strcasecmp(str, "false") ||
- !strcasecmp(str, "off") ||
- !strcasecmp(str, "0") ) {
- return ( LDAP_OFF );
- }
- return (-1);
- }
- int
- check_pw_minage_value( const char *attr_name, char *value, long minval, long maxval, char *errorbuf )
- {
- int retVal = LDAP_SUCCESS;
- int age;
- char *endPtr = NULL;
- age = strtol(value, &endPtr, 0 );
- if ( (age < 0) ||
- (age > (MAX_ALLOWED_TIME_IN_SECS - current_time())) ||
- (endPtr == NULL) || (endPtr == value) || !isdigit(*(endPtr-1)) )
- {
- PR_snprintf ( errorbuf, BUFSIZ,
- "password minimum age \"%s\" seconds is invalid. ",
- value );
- retVal = LDAP_CONSTRAINT_VIOLATION;
- }
- return retVal;
- }
- int
- check_pw_lockduration_value( const char *attr_name, char *value, long minval, long maxval, char *errorbuf )
- {
- int retVal = LDAP_SUCCESS;
- long duration = 0; /* in minutes */
- /* in seconds */
- duration = strtol (value, NULL, 0);
- if ( duration <= 0 || duration > (MAX_ALLOWED_TIME_IN_SECS - current_time()) ) {
- PR_snprintf ( errorbuf, BUFSIZ,
- "password lockout duration \"%s\" seconds is invalid. ",
- value );
- retVal = LDAP_CONSTRAINT_VIOLATION;
- }
- return retVal;
- }
- int
- check_pw_resetfailurecount_value( const char *attr_name, char *value, long minval, long maxval, char *errorbuf )
- {
- int retVal = LDAP_SUCCESS;
- long duration = 0; /* in minutes */
- /* in seconds */
- duration = strtol (value, NULL, 0);
- if ( duration < 0 || duration > (MAX_ALLOWED_TIME_IN_SECS - current_time()) ) {
- PR_snprintf ( errorbuf, BUFSIZ,
- "password reset count duration \"%s\" seconds is invalid. ",
- value );
- retVal = LDAP_CONSTRAINT_VIOLATION;
- }
- return retVal;
- }
- int
- check_pw_storagescheme_value( const char *attr_name, char *value, long minval, long maxval, char *errorbuf )
- {
- int retVal = LDAP_SUCCESS;
- struct pw_scheme *new_scheme = NULL;
- char * scheme_list = NULL;
- scheme_list = plugin_get_pwd_storage_scheme_list(PLUGIN_LIST_PWD_STORAGE_SCHEME);
- new_scheme = pw_name2scheme(value);
- if ( new_scheme == NULL) {
- if ( scheme_list != NULL ) {
- PR_snprintf ( errorbuf, BUFSIZ,
- "%s: invalid scheme - %s. Valid schemes are: %s",
- CONFIG_PW_STORAGESCHEME_ATTRIBUTE, value, scheme_list );
- } else {
- PR_snprintf ( errorbuf, BUFSIZ,
- "%s: invalid scheme - %s (no pwdstorage scheme"
- " plugin loaded)",
- CONFIG_PW_STORAGESCHEME_ATTRIBUTE, value);
- }
- retVal = LDAP_CONSTRAINT_VIOLATION;
- }
- else if ( new_scheme->pws_enc == NULL )
- {
- /* For example: the NS-MTA-MD5 password scheme is for comparision only
- and for backward compatibility with an Old Messaging Server that was
- setting passwords in the directory already encrypted. The scheme cannot
- and won't encrypt passwords if they are in clear. We don't take it
- */
- if ( scheme_list != NULL ) {
- PR_snprintf ( errorbuf, BUFSIZ,
- "%s: invalid encoding scheme - %s\nValid values are: %s\n",
- CONFIG_PW_STORAGESCHEME_ATTRIBUTE, value, scheme_list );
- }
- retVal = LDAP_CONSTRAINT_VIOLATION;
- }
-
- free_pw_scheme(new_scheme);
- slapi_ch_free_string(&scheme_list);
- return retVal;
- }
|