| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825 |
- /** 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 **/
- /*
- * 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;
- char *enc;
- 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;
- if ( (pwsp=pw_val2scheme( (char*)slapi_value_get_string(vals[ i ]), NULL, 0)) != NULL ) { /* JCM Innards */
- free_pw_scheme( pwsp );
- continue; /* don't touch pre-encoded values */
- }
- if (( 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;
- 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 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] )) )
- {
- if ( pwresponse_req == 1 ) {
- slapi_pwpolicy_make_response_control ( pb, -1, -1,
- LDAP_PWPOLICY_PWDTOOSHORT );
- }
- pw_send_ldap_result ( pb,
- LDAP_CONSTRAINT_VIOLATION, NULL,
- "invalid password syntax", 0, NULL );
- delete_passwdPolicy(&pwpolicy);
- return ( 1 );
- }
- /* check character types */
- pwd = (char *)slapi_value_get_string( vals[i] );
- p = pwd;
- /*
- pwdlen = slapi_value_get_length( vals[i] );
- for ( j = 0; j < pwdlen; j++ ) {
- */
- while ( p && *p )
- {
- if ( ldap_utf8isdigit( p ) ) {
- num_digits++;
- } else if ( ldap_utf8isalpha( p ) ) {
- num_alphas++;
- if ( slapi_utf8isLower( 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 ) ||
- ( pwpolicy->pw_minalphas > num_alphas ) ||
- ( pwpolicy->pw_minuppers > num_uppers ) ||
- ( pwpolicy->pw_minlowers > num_lowers ) ||
- ( pwpolicy->pw_minspecials > num_specials ) ||
- ( pwpolicy->pw_min8bit > num_8bit ) ||
- ( (pwpolicy->pw_maxrepeats != 0) && (pwpolicy->pw_maxrepeats < (max_repeated + 1)) ) ||
- ( pwpolicy->pw_mincategories > num_categories ) )
- {
- 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", 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;
- vs = slapi_valueset_new();
- 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)) )
- {
- /* Add present values to valueset */
- slapi_attr_get_valueset( attr, &vs );
- }
- }
- /* 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", 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;
- }
-
- slapi_ch_free_string(&scheme_list);
- return retVal;
- }
|