pw.c 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. /*
  39. * slapd hashed password routines
  40. *
  41. */
  42. #include <stdio.h>
  43. #include <string.h>
  44. #include <sys/types.h>
  45. #include <sechash.h>
  46. #if defined( _WIN32 )
  47. #undef DEBUG
  48. #endif /* _WIN32 */
  49. #if defined( _WIN32 )
  50. #undef LDAPDebug
  51. #endif /* _WIN32 */
  52. #include "slap.h"
  53. #define DENY_PW_CHANGE_ACI "(targetattr = \"userPassword\") ( version 3.0; acl \"disallow_pw_change_aci\"; deny (write ) userdn = \"ldap:///self\";)"
  54. #define GENERALIZED_TIME_LENGTH 15
  55. static int pw_in_history(Slapi_Value **history_vals, const Slapi_Value *pw_val);
  56. static int update_pw_history( Slapi_PBlock *pb, char *dn, char *old_pw );
  57. static int check_trivial_words (Slapi_PBlock *, Slapi_Entry *, Slapi_Value **,
  58. char *attrtype, int toklen, Slapi_Mods *smods );
  59. static int pw_boolean_str2value (const char *str);
  60. /* static LDAPMod* pw_malloc_mod (char* name, char* value, int mod_op); */
  61. /*
  62. * We want to be able to return errors to internal operations (which
  63. * can come from the password change extended operation). So we have
  64. * a special result function that does the right thing for an internal op.
  65. */
  66. static void
  67. pw_send_ldap_result(
  68. Slapi_PBlock *pb,
  69. int err,
  70. char *matched,
  71. char *text,
  72. int nentries,
  73. struct berval **urls
  74. )
  75. {
  76. int internal_op = 0;
  77. Slapi_Operation *operation = NULL;
  78. slapi_pblock_get (pb, SLAPI_OPERATION, &operation);
  79. internal_op= operation_is_flag_set(operation, OP_FLAG_INTERNAL);
  80. if (internal_op) {
  81. slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_RESULT, &err);
  82. } else {
  83. send_ldap_result(pb, err, matched, text, nentries, urls);
  84. }
  85. }
  86. /*
  87. * Like slapi_value_find, except for passwords.
  88. * returns 0 if password "v" is found in "vals"; non-zero otherwise
  89. */
  90. SLAPI_DEPRECATED int
  91. slapi_pw_find(
  92. struct berval **vals,
  93. struct berval *v
  94. )
  95. {
  96. int rc;
  97. Slapi_Value **svin_vals= NULL;
  98. Slapi_Value svin_v;
  99. slapi_value_init_berval(&svin_v,v);
  100. valuearray_init_bervalarray(vals,&svin_vals); /* JCM SLOW FUNCTION */
  101. rc= slapi_pw_find_sv(svin_vals,&svin_v);
  102. valuearray_free(&svin_vals);
  103. value_done(&svin_v);
  104. return rc;
  105. }
  106. /*
  107. * Like slapi_value_find, except for passwords.
  108. * returns 0 if password "v" is found in "vals"; non-zero otherwise
  109. */
  110. int
  111. slapi_pw_find_sv(
  112. Slapi_Value **vals,
  113. const Slapi_Value *v
  114. )
  115. {
  116. struct pw_scheme *pwsp;
  117. char *valpwd;
  118. int i;
  119. LDAPDebug( LDAP_DEBUG_TRACE, "=> slapi_pw_find value: \"%s\"\n", slapi_value_get_string(v), 0, 0 ); /* JCM Innards */
  120. for ( i = 0; vals[i] != NULL; i++ )
  121. {
  122. pwsp = pw_val2scheme( (char*)slapi_value_get_string(vals[i]), &valpwd, 1 ); /* JCM Innards*/
  123. if ( pwsp != NULL &&
  124. (*(pwsp->pws_cmp))( (char*)slapi_value_get_string(v), valpwd ) == 0 ) /* JCM Innards*/
  125. {
  126. LDAPDebug( LDAP_DEBUG_TRACE,
  127. "<= slapi_pw_find matched \"%s\" using scheme \"%s\"\n",
  128. valpwd, pwsp->pws_name, 0 );
  129. free_pw_scheme( pwsp );
  130. return( 0 ); /* found it */
  131. }
  132. free_pw_scheme( pwsp );
  133. }
  134. LDAPDebug( LDAP_DEBUG_TRACE, "<= slapi_pw_find no matching password\n", 0, 0, 0 );
  135. return( 1 ); /* no match */
  136. }
  137. /* Checks if the specified value is encoded.
  138. Returns 1 if it is and 0 otherwise
  139. */
  140. int slapi_is_encoded (char *value)
  141. {
  142. struct pw_scheme *is_hashed = NULL;
  143. int is_encoded = 0;
  144. is_hashed = pw_val2scheme ( value, NULL, 0 );
  145. if ( is_hashed != NULL )
  146. {
  147. free_pw_scheme( is_hashed );
  148. is_encoded = 1;
  149. }
  150. return (is_encoded);
  151. }
  152. char* slapi_encode (char *value, char *alg)
  153. {
  154. struct pw_scheme *enc_scheme = NULL;
  155. char *hashedval = NULL;
  156. int need_to_free = 0;
  157. if (alg == NULL) /* use server encoding scheme */
  158. {
  159. slapdFrontendConfig_t * slapdFrontendConfig = getFrontendConfig();
  160. enc_scheme = slapdFrontendConfig->pw_storagescheme;
  161. if (enc_scheme == NULL)
  162. {
  163. slapi_log_error( SLAPI_LOG_FATAL, NULL,
  164. "slapi_encode: no server scheme\n" );
  165. return NULL;
  166. }
  167. }
  168. else
  169. {
  170. enc_scheme = pw_name2scheme(alg);
  171. if ( enc_scheme == NULL)
  172. {
  173. char * scheme_list = plugin_get_pwd_storage_scheme_list(PLUGIN_LIST_PWD_STORAGE_SCHEME);
  174. if ( scheme_list != NULL ) {
  175. slapi_log_error( SLAPI_LOG_FATAL, NULL,
  176. "slapi_encode: invalid scheme - %s\n"
  177. "Valid values are: %s\n", alg, scheme_list );
  178. slapi_ch_free((void **)&scheme_list);
  179. } else {
  180. slapi_log_error( SLAPI_LOG_FATAL, NULL,
  181. "slapi_encode: invalid scheme - %s\n"
  182. "no pwdstorage scheme plugin loaded", alg);
  183. }
  184. return NULL;
  185. }
  186. need_to_free = 1;
  187. }
  188. hashedval = enc_scheme->pws_enc(value);
  189. if (need_to_free)
  190. free_pw_scheme(enc_scheme);
  191. return hashedval;
  192. }
  193. /*
  194. * Return a pointer to the pw_scheme struct for scheme "name"
  195. * NULL is returned is no matching scheme is found.
  196. */
  197. struct pw_scheme *
  198. pw_name2scheme( char *name )
  199. {
  200. struct pw_scheme *pwsp;
  201. struct slapdplugin *p;
  202. if ( (p = plugin_get_pwd_storage_scheme(name, strlen(name), PLUGIN_LIST_PWD_STORAGE_SCHEME)) != NULL ) {
  203. pwsp = (struct pw_scheme *) slapi_ch_malloc (sizeof(struct pw_scheme));
  204. if ( pwsp != NULL ) {
  205. typedef int (*CMPFP)(char *, char *);
  206. typedef char * (*ENCFP)(char *);
  207. pwsp->pws_name = slapi_ch_strdup( p->plg_pwdstorageschemename );
  208. pwsp->pws_cmp = (CMPFP)p->plg_pwdstorageschemecmp;
  209. pwsp->pws_enc = (ENCFP)p->plg_pwdstorageschemeenc;
  210. pwsp->pws_len = strlen(pwsp->pws_name) ;
  211. return(pwsp);
  212. }
  213. }
  214. return( NULL );
  215. }
  216. void free_pw_scheme(struct pw_scheme *pwsp)
  217. {
  218. if ( pwsp != NULL )
  219. {
  220. slapi_ch_free( (void**)&pwsp->pws_name );
  221. slapi_ch_free( (void**)&pwsp );
  222. }
  223. }
  224. /*
  225. * Return the password scheme for value "val". This is determined by
  226. * checking "val" against our scheme prefixes.
  227. *
  228. * If "valpwdp" is not NULL, it is set to point to the value with any
  229. * prefix removed.
  230. *
  231. * If no matching scheme is found and first_is_default is non-zero, the
  232. * first scheme is returned. If no matching scheme is found and
  233. * first_is_default is zero, NULL is returned.
  234. */
  235. struct pw_scheme *
  236. pw_val2scheme( char *val, char **valpwdp, int first_is_default )
  237. {
  238. struct pw_scheme *pwsp;
  239. int namelen, prefixlen;
  240. char *end, buf[ PWD_MAX_NAME_LEN + 1 ];
  241. if ( *val != PWD_HASH_PREFIX_START ||
  242. ( end = strchr( val, PWD_HASH_PREFIX_END )) == NULL ||
  243. ( namelen = end - val - 1 ) > PWD_MAX_NAME_LEN ) {
  244. if ( !first_is_default ) {
  245. return( NULL );
  246. }
  247. pwsp = pw_name2scheme("CLEAR"); /* default to first scheme */
  248. prefixlen = 0;
  249. } else {
  250. memcpy( buf, val + 1, namelen );
  251. buf[ namelen ] = '\0';
  252. pwsp = pw_name2scheme(buf);
  253. if ( pwsp == NULL ) {
  254. if ( !first_is_default ) {
  255. return( NULL );
  256. }
  257. pwsp = pw_name2scheme("CLEAR");
  258. prefixlen = 0;
  259. } else {
  260. prefixlen = pwsp->pws_len + 2;
  261. }
  262. }
  263. if ( valpwdp != NULL ) {
  264. *valpwdp = val + prefixlen;
  265. }
  266. return( pwsp );
  267. }
  268. /*
  269. * re-encode the password values in "vals" using a hashing algorithm
  270. * vals[n] is assumed to be an alloc'd Slapi_Value that can be free'd and
  271. * replaced. If a value is already encoded, we do not re-encode it.
  272. * Return 0 if all goes well and < 0 if an error occurs.
  273. */
  274. int
  275. pw_encodevals( Slapi_Value **vals )
  276. {
  277. int i;
  278. char *enc;
  279. slapdFrontendConfig_t * slapdFrontendConfig = getFrontendConfig();
  280. if ( vals == NULL || slapdFrontendConfig->pw_storagescheme == NULL ||
  281. slapdFrontendConfig->pw_storagescheme->pws_enc == NULL ) {
  282. return( 0 );
  283. }
  284. for ( i = 0; vals[ i ] != NULL; ++i ) {
  285. struct pw_scheme *pwsp;
  286. if ( (pwsp=pw_val2scheme( (char*)slapi_value_get_string(vals[ i ]), NULL, 0)) != NULL ) { /* JCM Innards */
  287. free_pw_scheme( pwsp );
  288. continue; /* don't touch pre-encoded values */
  289. }
  290. if (( enc = (*slapdFrontendConfig->pw_storagescheme->pws_enc)( (char*)slapi_value_get_string(vals[ i ]) )) /* JCM Innards */
  291. == NULL ) {
  292. free_pw_scheme( pwsp );
  293. return( -1 );
  294. }
  295. slapi_value_free(&vals[ i ]);
  296. vals[ i ] = slapi_value_new_string_passin(enc);
  297. free_pw_scheme( pwsp );
  298. }
  299. return( 0 );
  300. }
  301. /*
  302. * Check if the prefix of the cipher is the one that is supposed to be
  303. * Extract from the whole cipher the encrypted password (remove the prefix)
  304. */
  305. int checkPrefix(char *cipher, char *schemaName, char **encrypt)
  306. {
  307. int namelen;
  308. /* buf contains the extracted schema name */
  309. char *end, buf[ 3*PWD_MAX_NAME_LEN + 1 ];
  310. if ( (*cipher == PWD_HASH_PREFIX_START) &&
  311. ((end = strchr(cipher, PWD_HASH_PREFIX_END)) != NULL) &&
  312. ((namelen = end - cipher - 1 ) <= (3*PWD_MAX_NAME_LEN)) )
  313. {
  314. memcpy( buf, cipher + 1, namelen );
  315. buf[ namelen ] = '\0';
  316. if ( strcasecmp( buf, schemaName) != 0 )
  317. {
  318. /* schema names are different, error */
  319. return 1;
  320. }
  321. else
  322. {
  323. /* extract the encrypted password */
  324. *encrypt = cipher + strlen(schemaName) + 2;
  325. return 0;
  326. }
  327. }
  328. /* cipher is not prefixed, already in clear ? */
  329. return -1;
  330. }
  331. /*
  332. * Decode the attribute "attr_name" with one of the reversible encryption mechanism
  333. * Returns -1 on error
  334. * Returns 0 on success with strdup'ed plain
  335. * Returns 1 on success with *plain=cipher
  336. */
  337. int
  338. pw_rever_decode(char *cipher, char **plain, const char * attr_name)
  339. {
  340. struct pw_scheme *pwsp = NULL;
  341. struct slapdplugin *p = NULL;
  342. int ret_code = 1;
  343. for ( p = get_plugin_list(PLUGIN_LIST_REVER_PWD_STORAGE_SCHEME); p != NULL; p = p->plg_next )
  344. {
  345. char *L_attr = NULL;
  346. int i = 0;
  347. char *encrypt = NULL;
  348. int prefixOK = -1;
  349. /* Get the appropriate decoding function */
  350. for ( L_attr = p->plg_argv[i]; i<p->plg_argc; L_attr = p->plg_argv[++i] )
  351. {
  352. if (slapi_attr_types_equivalent(L_attr, attr_name))
  353. {
  354. typedef int (*CMPFP)(char *, char *);
  355. typedef char * (*ENCFP)(char *);
  356. pwsp = (struct pw_scheme *) slapi_ch_calloc (1, sizeof(struct pw_scheme));
  357. pwsp->pws_dec = (ENCFP)p->plg_pwdstorageschemedec;
  358. pwsp->pws_name = slapi_ch_strdup( p->plg_pwdstorageschemename );
  359. pwsp->pws_len = strlen(pwsp->pws_name) ;
  360. if ( pwsp->pws_dec != NULL )
  361. {
  362. /* check that the prefix of the cipher is the same name
  363. as the schema name */
  364. prefixOK = checkPrefix(cipher, pwsp->pws_name, &encrypt);
  365. if ( prefixOK == -1 )
  366. {
  367. /* no prefix, already in clear ? */
  368. *plain = cipher;
  369. ret_code = 1;
  370. goto free_and_return;
  371. }
  372. else if ( prefixOK == 1 )
  373. {
  374. /* schema names are different */
  375. ret_code = -1;
  376. goto free_and_return;
  377. }
  378. else
  379. {
  380. if ( ( *plain = (pwsp->pws_dec)( encrypt )) == NULL )
  381. {
  382. /* pb during decoding */
  383. ret_code = -1;
  384. goto free_and_return;
  385. }
  386. /* decoding is OK */
  387. ret_code = 0;
  388. goto free_and_return;
  389. }
  390. }
  391. free_pw_scheme( pwsp );
  392. pwsp = NULL;
  393. }
  394. }
  395. }
  396. free_and_return:
  397. if ( pwsp != NULL )
  398. {
  399. free_pw_scheme( pwsp );
  400. }
  401. return(ret_code);
  402. }
  403. /*
  404. * Encode the attribute "attr_name" with one of the reversible encryption mechanism
  405. */
  406. int
  407. pw_rever_encode(Slapi_Value **vals, char * attr_name)
  408. {
  409. char *enc;
  410. struct pw_scheme *pwsp = NULL;
  411. struct slapdplugin *p;
  412. if (vals == NULL){
  413. return (0);
  414. }
  415. for ( p = get_plugin_list(PLUGIN_LIST_REVER_PWD_STORAGE_SCHEME); p != NULL; p = p->plg_next )
  416. {
  417. char *L_attr = NULL;
  418. int i = 0;
  419. /* Get the appropriate encoding function */
  420. for ( L_attr = p->plg_argv[i]; i<p->plg_argc; L_attr = p->plg_argv[++i] )
  421. {
  422. if (slapi_attr_types_equivalent(L_attr, attr_name))
  423. {
  424. typedef int (*CMPFP)(char *, char *);
  425. typedef char * (*ENCFP)(char *);
  426. pwsp = (struct pw_scheme *) slapi_ch_calloc (1, sizeof(struct pw_scheme));
  427. pwsp->pws_enc = (ENCFP)p->plg_pwdstorageschemeenc;
  428. pwsp->pws_name = slapi_ch_strdup( p->plg_pwdstorageschemename );
  429. if ( pwsp->pws_enc != NULL )
  430. {
  431. for ( i = 0; vals[i] != NULL; ++i )
  432. {
  433. char *encrypt = NULL;
  434. int prefixOK;
  435. prefixOK = checkPrefix((char*)slapi_value_get_string(vals[i]),
  436. pwsp->pws_name,
  437. &encrypt);
  438. if ( prefixOK == 0 )
  439. {
  440. /* Don't touch already encoded value */
  441. continue; /* don't touch pre-encoded values */
  442. }
  443. else if (prefixOK == 1 )
  444. {
  445. /* credential is already encoded, but not with this schema. Error */
  446. free_pw_scheme( pwsp );
  447. return( -1 );
  448. }
  449. if ( ( enc = (pwsp->pws_enc)( (char*)slapi_value_get_string(vals[ i ]) )) == NULL )
  450. {
  451. free_pw_scheme( pwsp );
  452. return( -1 );
  453. }
  454. slapi_value_free(&vals[ i ]);
  455. vals[ i ] = slapi_value_new_string_passin(enc);
  456. free_pw_scheme( pwsp );
  457. return (0);
  458. }
  459. }
  460. }
  461. }
  462. }
  463. free_pw_scheme( pwsp );
  464. return(-1);
  465. }
  466. /* ONREPL - below are the functions moved from pw_mgmt.c.
  467. this is done to allow the functions to be used
  468. by functions linked into libslapd.
  469. */
  470. /* update_pw_info is called after password is modified successfully */
  471. /* it should update passwordHistory, and passwordExpirationTime */
  472. /* SLAPI_ENTRY_POST_OP must be set */
  473. int
  474. update_pw_info ( Slapi_PBlock *pb , char *old_pw) {
  475. Slapi_Mods smods;
  476. char *timestr;
  477. time_t pw_exp_date;
  478. time_t cur_time;
  479. char *dn;
  480. passwdPolicy *pwpolicy = NULL;
  481. cur_time = current_time();
  482. slapi_pblock_get( pb, SLAPI_TARGET_DN, &dn );
  483. pwpolicy = new_passwdPolicy(pb, dn);
  484. /* update passwordHistory */
  485. if ( old_pw != NULL && pwpolicy->pw_history == 1 ) {
  486. update_pw_history(pb, dn, old_pw);
  487. slapi_ch_free ( (void**)&old_pw );
  488. }
  489. slapi_mods_init(&smods, 0);
  490. /* update password allow change time */
  491. if ( pwpolicy->pw_minage != 0) {
  492. timestr = format_genTime( time_plus_sec( cur_time,
  493. pwpolicy->pw_minage ));
  494. slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordAllowChangeTime", timestr);
  495. slapi_ch_free((void **)&timestr);
  496. }
  497. /* Fix for Bug 560707
  498. Removed the restriction that the lock variables (retry count) will
  499. be set only when root resets the passwd.
  500. Now admins will also have these privileges.
  501. */
  502. if (pwpolicy->pw_lockout) {
  503. set_retry_cnt_mods (pb, &smods, 0 );
  504. }
  505. /* Clear the passwordgraceusertime from the user entry */
  506. slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordgraceusertime", "0");
  507. /* if the password is reset by root, mark it the first time logon */
  508. if ( pb->pb_requestor_isroot == 1 &&
  509. pwpolicy->pw_must_change){
  510. pw_exp_date = NO_TIME;
  511. } else if ( pwpolicy->pw_exp == 1 ) {
  512. Slapi_Entry *pse = NULL;
  513. /* update password expiration date */
  514. pw_exp_date = time_plus_sec ( cur_time,
  515. pwpolicy->pw_maxage );
  516. slapi_pblock_get(pb,SLAPI_ENTRY_POST_OP,&pse);
  517. if (pse) {
  518. char *prev_exp_date_str;
  519. /* if the password expiry time is SLAPD_END_TIME,
  520. * don't roll it back
  521. */
  522. prev_exp_date_str = slapi_entry_attr_get_charptr(pse,"passwordExpirationTime");
  523. if (prev_exp_date_str) {
  524. time_t prev_exp_date;
  525. prev_exp_date = parse_genTime(prev_exp_date_str);
  526. if (prev_exp_date == NO_TIME ||
  527. prev_exp_date == NOT_FIRST_TIME) {
  528. /* ignore as will replace */
  529. } else if (prev_exp_date == SLAPD_END_TIME) {
  530. /* Special entries' passwords never expire */
  531. slapi_ch_free((void**)&prev_exp_date_str);
  532. pw_apply_mods(dn, &smods);
  533. slapi_mods_done(&smods);
  534. delete_passwdPolicy(&pwpolicy);
  535. return 0;
  536. }
  537. slapi_ch_free((void**)&prev_exp_date_str);
  538. }
  539. } /* post op entry */
  540. } else if (pwpolicy->pw_must_change) {
  541. /*
  542. * pw is not changed by root, and must change pw first time
  543. * log on
  544. */
  545. pw_exp_date = NOT_FIRST_TIME;
  546. } else {
  547. pw_apply_mods(dn, &smods);
  548. slapi_mods_done(&smods);
  549. delete_passwdPolicy(&pwpolicy);
  550. return 0;
  551. }
  552. delete_passwdPolicy(&pwpolicy);
  553. timestr = format_genTime ( pw_exp_date );
  554. slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordExpirationTime", timestr);
  555. slapi_ch_free((void **)&timestr);
  556. slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordExpWarned", "0");
  557. pw_apply_mods(dn, &smods);
  558. slapi_mods_done(&smods);
  559. if (pb->pb_conn) { /* no conn for internal op */
  560. /* reset c_needpw to 0 */
  561. pb->pb_conn->c_needpw = 0;
  562. }
  563. return 0;
  564. }
  565. int
  566. check_pw_minage ( Slapi_PBlock *pb, const Slapi_DN *sdn, struct berval **vals)
  567. {
  568. char *dn= (char*)slapi_sdn_get_ndn(sdn); /* jcm - Had to cast away const */
  569. passwdPolicy *pwpolicy=NULL;
  570. int pwresponse_req = 0;
  571. pwpolicy = new_passwdPolicy(pb, dn);
  572. slapi_pblock_get ( pb, SLAPI_PWPOLICY, &pwresponse_req );
  573. if ( !pb->pb_op->o_isroot &&
  574. pwpolicy->pw_minage != 0 ) {
  575. Slapi_Entry *e;
  576. char *passwordAllowChangeTime;
  577. /* retrieve the entry */
  578. e = get_entry ( pb, dn );
  579. if ( e == NULL ) {
  580. delete_passwdPolicy(&pwpolicy);
  581. return ( -1 );
  582. }
  583. /* get passwordAllowChangeTime attribute */
  584. passwordAllowChangeTime= slapi_entry_attr_get_charptr(e, "passwordAllowChangeTime");
  585. if (passwordAllowChangeTime!=NULL)
  586. {
  587. time_t pw_allowchange_date;
  588. char *cur_time_str = NULL;
  589. pw_allowchange_date = parse_genTime(passwordAllowChangeTime);
  590. slapi_ch_free((void **) &passwordAllowChangeTime );
  591. /* check if allow to change the password */
  592. cur_time_str = format_genTime ( current_time() );
  593. if ( difftime ( pw_allowchange_date,
  594. parse_genTime ( cur_time_str )) > 0 )
  595. {
  596. if ( pwresponse_req == 1 ) {
  597. slapi_pwpolicy_make_response_control ( pb, -1, -1,
  598. LDAP_PWPOLICY_PWDTOOYOUNG );
  599. }
  600. pw_send_ldap_result ( pb,
  601. LDAP_CONSTRAINT_VIOLATION, NULL,
  602. "within password minimum age", 0, NULL );
  603. slapi_entry_free( e );
  604. slapi_ch_free((void **) &cur_time_str );
  605. delete_passwdPolicy(&pwpolicy);
  606. return ( 1 );
  607. }
  608. slapi_ch_free((void **) &cur_time_str );
  609. }
  610. slapi_entry_free( e );
  611. }
  612. delete_passwdPolicy(&pwpolicy);
  613. return ( 0 );
  614. }
  615. /* check_pw_syntax is called before add or modify operation on userpassword attribute*/
  616. int
  617. check_pw_syntax ( Slapi_PBlock *pb, const Slapi_DN *sdn, Slapi_Value **vals,
  618. char **old_pw, Slapi_Entry *e, int mod_op)
  619. {
  620. return ( check_pw_syntax_ext(pb, sdn, vals, old_pw, e, mod_op, NULL) );
  621. }
  622. int
  623. check_pw_syntax_ext ( Slapi_PBlock *pb, const Slapi_DN *sdn, Slapi_Value **vals,
  624. char **old_pw, Slapi_Entry *e, int mod_op, Slapi_Mods *smods)
  625. {
  626. Slapi_Attr* attr;
  627. int i, pwresponse_req = 0;
  628. char *dn= (char*)slapi_sdn_get_ndn(sdn); /* jcm - Had to cast away const */
  629. char *pwd = NULL;
  630. char *p = NULL;
  631. passwdPolicy *pwpolicy = NULL;
  632. pwpolicy = new_passwdPolicy(pb, dn);
  633. slapi_pblock_get ( pb, SLAPI_PWPOLICY, &pwresponse_req );
  634. if ( pwpolicy->pw_syntax == 1 ) {
  635. for ( i = 0; vals[ i ] != NULL; ++i ) {
  636. int num_digits = 0;
  637. int num_alphas = 0;
  638. int num_uppers = 0;
  639. int num_lowers = 0;
  640. int num_specials = 0;
  641. int num_8bit = 0;
  642. int num_repeated = 0;
  643. int max_repeated = 0;
  644. int num_categories = 0;
  645. /* check for the minimum password length */
  646. if ( pwpolicy->pw_minlength >
  647. ldap_utf8characters((char *)slapi_value_get_string( vals[i] )) )
  648. {
  649. if ( pwresponse_req == 1 ) {
  650. slapi_pwpolicy_make_response_control ( pb, -1, -1,
  651. LDAP_PWPOLICY_PWDTOOSHORT );
  652. }
  653. pw_send_ldap_result ( pb,
  654. LDAP_CONSTRAINT_VIOLATION, NULL,
  655. "invalid password syntax", 0, NULL );
  656. delete_passwdPolicy(&pwpolicy);
  657. return ( 1 );
  658. }
  659. /* check character types */
  660. pwd = (char *)slapi_value_get_string( vals[i] );
  661. p = pwd;
  662. /*
  663. pwdlen = slapi_value_get_length( vals[i] );
  664. for ( j = 0; j < pwdlen; j++ ) {
  665. */
  666. while ( p && *p )
  667. {
  668. if ( ldap_utf8isdigit( p ) ) {
  669. num_digits++;
  670. } else if ( ldap_utf8isalpha( p ) ) {
  671. num_alphas++;
  672. if ( slapi_utf8isLower( p ) ) {
  673. num_lowers++;
  674. } else {
  675. num_uppers++;
  676. }
  677. } else {
  678. /* check if this is an 8-bit char */
  679. if ( *p & 128 ) {
  680. num_8bit++;
  681. } else {
  682. num_specials++;
  683. }
  684. }
  685. /* check for repeating characters. If this is the
  686. first char of the password, no need to check */
  687. if ( pwd != p ) {
  688. int len = ldap_utf8len( p );
  689. char *prev_p = ldap_utf8prev( p );
  690. if ( len == ldap_utf8len( prev_p ) )
  691. {
  692. if ( memcmp( p, prev_p, len ) == 0 )
  693. {
  694. num_repeated++;
  695. if ( max_repeated < num_repeated ) {
  696. max_repeated = num_repeated;
  697. }
  698. } else {
  699. num_repeated = 0;
  700. }
  701. } else {
  702. num_repeated = 0;
  703. }
  704. }
  705. p = ldap_utf8next( p );
  706. }
  707. /* tally up the number of character categories */
  708. if ( num_digits > 0 )
  709. ++num_categories;
  710. if ( num_uppers > 0 )
  711. ++num_categories;
  712. if ( num_lowers > 0 )
  713. ++num_categories;
  714. if ( num_specials > 0 )
  715. ++num_categories;
  716. if ( num_8bit > 0 )
  717. ++num_categories;
  718. /* check for character based syntax limits */
  719. if ( ( pwpolicy->pw_mindigits > num_digits ) ||
  720. ( pwpolicy->pw_minalphas > num_alphas ) ||
  721. ( pwpolicy->pw_minuppers > num_uppers ) ||
  722. ( pwpolicy->pw_minlowers > num_lowers ) ||
  723. ( pwpolicy->pw_minspecials > num_specials ) ||
  724. ( pwpolicy->pw_min8bit > num_8bit ) ||
  725. ( (pwpolicy->pw_maxrepeats != 0) && (pwpolicy->pw_maxrepeats < (max_repeated + 1)) ) ||
  726. ( pwpolicy->pw_mincategories > num_categories ) )
  727. {
  728. if ( pwresponse_req == 1 ) {
  729. slapi_pwpolicy_make_response_control ( pb, -1, -1,
  730. LDAP_PWPOLICY_INVALIDPWDSYNTAX );
  731. }
  732. pw_send_ldap_result ( pb,
  733. LDAP_CONSTRAINT_VIOLATION, NULL,
  734. "invalid password syntax", 0, NULL );
  735. delete_passwdPolicy(&pwpolicy);
  736. return ( 1 );
  737. }
  738. }
  739. }
  740. /* get the entry and check for the password history if this is called by a modify operation */
  741. if ( mod_op ) {
  742. /* retrieve the entry */
  743. e = get_entry ( pb, dn );
  744. if ( e == NULL ) {
  745. delete_passwdPolicy(&pwpolicy);
  746. return ( -1 );
  747. }
  748. /* check for password history */
  749. if ( pwpolicy->pw_history == 1 ) {
  750. attr = attrlist_find(e->e_attrs, "passwordHistory");
  751. if (attr &&
  752. !valueset_isempty(&attr->a_present_values))
  753. {
  754. Slapi_Value **va= attr_get_present_values(attr);
  755. if ( pw_in_history( va, vals[0] ) == 0 ) {
  756. if ( pwresponse_req == 1 ) {
  757. slapi_pwpolicy_make_response_control ( pb, -1, -1,
  758. LDAP_PWPOLICY_PWDINHISTORY );
  759. }
  760. pw_send_ldap_result ( pb,
  761. LDAP_CONSTRAINT_VIOLATION, NULL,
  762. "password in history", 0, NULL );
  763. slapi_entry_free( e );
  764. delete_passwdPolicy(&pwpolicy);
  765. return ( 1 );
  766. }
  767. }
  768. /* get current password. check it and remember it */
  769. attr = attrlist_find(e->e_attrs, "userpassword");
  770. if (attr && !valueset_isempty(&attr->a_present_values))
  771. {
  772. Slapi_Value **va= valueset_get_valuearray(&attr->a_present_values);
  773. if (slapi_is_encoded((char*)slapi_value_get_string(vals[0])))
  774. {
  775. if (slapi_attr_value_find(attr, (struct berval *)slapi_value_get_berval(vals[0])) == 0 )
  776. {
  777. pw_send_ldap_result ( pb,
  778. LDAP_CONSTRAINT_VIOLATION ,NULL,
  779. "password in history", 0, NULL);
  780. slapi_entry_free( e );
  781. delete_passwdPolicy(&pwpolicy);
  782. return ( 1 );
  783. }
  784. } else
  785. {
  786. if ( slapi_pw_find_sv ( va, vals[0] ) == 0 )
  787. {
  788. pw_send_ldap_result ( pb,
  789. LDAP_CONSTRAINT_VIOLATION ,NULL,
  790. "password in history", 0, NULL);
  791. slapi_entry_free( e );
  792. delete_passwdPolicy(&pwpolicy);
  793. return ( 1 );
  794. }
  795. }
  796. /* We copy the 1st value of the userpassword attribute.
  797. * This is because password policy assumes that there's only one
  798. * password in the userpassword attribute.
  799. */
  800. *old_pw = slapi_ch_strdup(slapi_value_get_string(va[0]));
  801. } else {
  802. *old_pw = NULL;
  803. }
  804. }
  805. }
  806. /* check for trivial words if syntax checking is enabled */
  807. if ( pwpolicy->pw_syntax == 1 ) {
  808. /* e is null if this is an add operation*/
  809. if ( check_trivial_words ( pb, e, vals, "uid", pwpolicy->pw_mintokenlength, smods ) == 1 ||
  810. check_trivial_words ( pb, e, vals, "cn", pwpolicy->pw_mintokenlength, smods ) == 1 ||
  811. check_trivial_words ( pb, e, vals, "sn", pwpolicy->pw_mintokenlength, smods ) == 1 ||
  812. check_trivial_words ( pb, e, vals, "givenname", pwpolicy->pw_mintokenlength, smods ) == 1 ||
  813. check_trivial_words ( pb, e, vals, "ou", pwpolicy->pw_mintokenlength, smods ) == 1 ||
  814. check_trivial_words ( pb, e, vals, "mail", pwpolicy->pw_mintokenlength, smods ) == 1)
  815. {
  816. if ( mod_op ) {
  817. slapi_entry_free( e );
  818. }
  819. delete_passwdPolicy(&pwpolicy);
  820. return 1;
  821. }
  822. }
  823. delete_passwdPolicy(&pwpolicy);
  824. if ( mod_op ) {
  825. /* free e only when called by modify operation */
  826. slapi_entry_free( e );
  827. }
  828. return 0; /* success */
  829. }
  830. static
  831. int update_pw_history( Slapi_PBlock *pb, char *dn, char *old_pw ) {
  832. time_t t, old_t, cur_time;
  833. int i = 0, oldest = 0;
  834. int res;
  835. Slapi_Entry *e;
  836. Slapi_Attr *attr;
  837. LDAPMod attribute;
  838. char *values_replace[25]; /* 2-24 passwords in history */
  839. LDAPMod *list_of_mods[2];
  840. Slapi_PBlock mod_pb;
  841. char *history_str;
  842. char *str;
  843. passwdPolicy *pwpolicy = NULL;
  844. pwpolicy = new_passwdPolicy(pb, dn);
  845. /* retrieve the entry */
  846. e = get_entry ( pb, dn );
  847. if ( e == NULL ) {
  848. delete_passwdPolicy(&pwpolicy);
  849. return ( 1 );
  850. }
  851. history_str = (char *)slapi_ch_malloc(GENERALIZED_TIME_LENGTH + strlen(old_pw) + 1);
  852. /* get password history, and find the oldest password in history */
  853. cur_time = current_time ();
  854. old_t = cur_time;
  855. str = format_genTime ( cur_time );
  856. attr = attrlist_find(e->e_attrs, "passwordHistory");
  857. if (attr && !valueset_isempty(&attr->a_present_values))
  858. {
  859. Slapi_Value **va= valueset_get_valuearray(&attr->a_present_values);
  860. for ( i = oldest = 0 ;
  861. (va[i] != NULL) && (slapi_value_get_length(va[i]) > 0) ;
  862. i++ ) {
  863. values_replace[i] = (char*)slapi_value_get_string(va[i]);
  864. strncpy( history_str, values_replace[i], GENERALIZED_TIME_LENGTH);
  865. history_str[GENERALIZED_TIME_LENGTH] = '\0';
  866. if (history_str[GENERALIZED_TIME_LENGTH - 1] != 'Z'){
  867. /* The time is not a generalized Time. Probably a password history from 4.x */
  868. history_str[GENERALIZED_TIME_LENGTH - 1] = '\0';
  869. }
  870. t = parse_genTime ( history_str );
  871. if ( difftime ( t, old_t ) < 0 ) {
  872. oldest = i;
  873. old_t = t;
  874. }
  875. }
  876. }
  877. strcpy ( history_str, str );
  878. strcat ( history_str, old_pw );
  879. if ( i == pwpolicy->pw_inhistory ) {
  880. /* replace the oldest password in history */
  881. values_replace [oldest] = history_str;
  882. values_replace[i]=NULL;
  883. } else {
  884. /* add old_pw at the end of password history */
  885. values_replace[i] = history_str;
  886. values_replace[++i]=NULL;
  887. }
  888. /* modify the attribute */
  889. attribute.mod_type = "passwordHistory";
  890. attribute.mod_op = LDAP_MOD_REPLACE;
  891. attribute.mod_values = values_replace;
  892. list_of_mods[0] = &attribute;
  893. list_of_mods[1] = NULL;
  894. pblock_init(&mod_pb);
  895. slapi_modify_internal_set_pb(&mod_pb, dn, list_of_mods, NULL, NULL,
  896. pw_get_componentID(), 0);
  897. slapi_modify_internal_pb(&mod_pb);
  898. slapi_pblock_get(&mod_pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
  899. if (res != LDAP_SUCCESS){
  900. LDAPDebug(LDAP_DEBUG_ANY, "WARNING: passwordPolicy modify error %d on entry '%s'\n",
  901. res, dn, 0);
  902. }
  903. pblock_done(&mod_pb);
  904. slapi_ch_free((void **) &str );
  905. slapi_ch_free((void **) &history_str );
  906. slapi_entry_free( e );
  907. delete_passwdPolicy(&pwpolicy);
  908. return 0;
  909. }
  910. static
  911. int pw_in_history( Slapi_Value **history_vals, const Slapi_Value *pw_val)
  912. {
  913. Slapi_Value *history[25];
  914. Slapi_Value historycv[25];
  915. int i;
  916. int ret = -1;
  917. const char *pw_str = slapi_value_get_string(pw_val);
  918. if (slapi_is_encoded((char*)pw_str)){
  919. /* If the password is encoded, we just do a string match with all previous passwords */
  920. for ( i = 0; history_vals[i] != NULL; i++){
  921. const char * h_val = slapi_value_get_string(history_vals[i]);
  922. if ( h_val != NULL &&
  923. slapi_value_get_length(history_vals[i]) >= 14 )
  924. {
  925. int pos = 14;
  926. if (h_val[pos] == 'Z')
  927. pos++;
  928. if (strcmp(&(h_val[pos]), pw_str) == 0){
  929. /* Password found */
  930. /* Let's just return */
  931. return (0);
  932. }
  933. }
  934. }
  935. }
  936. else { /* Password is in clear */
  937. /* strip the timestamps */
  938. for ( i = 0; history_vals[i] != NULL; i++ )
  939. {
  940. char *h_val = (char *)slapi_value_get_string(history_vals[i]);
  941. size_t h_len = slapi_value_get_length(history_vals[i]);
  942. historycv[i].v_csnset = NULL; /* JCM - I don't understand this */
  943. history[i] = &historycv[i];
  944. if ( h_val != NULL &&
  945. h_len >= 14 )
  946. {
  947. /* LP: With the new genTime, the password history format has changed */
  948. int pos = 14;
  949. if (h_val[pos] == 'Z')
  950. pos++;
  951. historycv[i].bv.bv_val = &(h_val[pos]);
  952. historycv[i].bv.bv_len = h_len - pos;
  953. } else {
  954. historycv[i].bv.bv_val = NULL;
  955. historycv[i].bv.bv_len = 0;
  956. }
  957. }
  958. history[i] = NULL;
  959. ret = slapi_pw_find_sv( history, pw_val);
  960. }
  961. return ( ret );
  962. }
  963. int
  964. slapi_add_pwd_control ( Slapi_PBlock *pb, char *arg, long time) {
  965. LDAPControl new_ctrl;
  966. char buf[12];
  967. LDAPDebug( LDAP_DEBUG_TRACE, "=> slapi_add_pwd_control\n", 0, 0, 0 );
  968. sprintf( buf, "%ld", time );
  969. new_ctrl.ldctl_oid = arg;
  970. new_ctrl.ldctl_value.bv_val = buf;
  971. new_ctrl.ldctl_value.bv_len = strlen( buf );
  972. new_ctrl.ldctl_iscritical = 0; /* 0 = false. */
  973. if ( slapi_pblock_set( pb, SLAPI_ADD_RESCONTROL, &new_ctrl ) != 0 ) {
  974. return( -1 );
  975. }
  976. return( 0 );
  977. }
  978. void
  979. pw_mod_allowchange_aci(int pw_prohibit_change) {
  980. const Slapi_DN *base;
  981. char *values_mod[2];
  982. LDAPMod mod;
  983. LDAPMod *mods[2];
  984. Slapi_Backend *be;
  985. char *cookie = NULL;
  986. mods[0] = &mod;
  987. mods[1] = NULL;
  988. mod.mod_type = "aci";
  989. mod.mod_values = values_mod;
  990. if (pw_prohibit_change) {
  991. mod.mod_op = LDAP_MOD_ADD;
  992. }
  993. else
  994. {
  995. /* Allow change password by default */
  996. /* remove the aci if it is there. it is ok to fail */
  997. mod.mod_op = LDAP_MOD_DELETE;
  998. }
  999. be = slapi_get_first_backend (&cookie);
  1000. /* Foreach backend... */
  1001. while (be)
  1002. {
  1003. /* Don't add aci on a chaining backend holding remote entries */
  1004. if((!be->be_private) && (!slapi_be_is_flag_set(be,SLAPI_BE_FLAG_REMOTE_DATA)))
  1005. {
  1006. /* There's only One suffix per DB now. No need to loop */
  1007. base = slapi_be_getsuffix(be, 0);
  1008. if (base != NULL)
  1009. {
  1010. Slapi_PBlock pb;
  1011. int rc;
  1012. pblock_init (&pb);
  1013. values_mod[0] = DENY_PW_CHANGE_ACI;
  1014. values_mod[1] = NULL;
  1015. slapi_modify_internal_set_pb(&pb, slapi_sdn_get_dn(base), mods, NULL, NULL, pw_get_componentID(), 0);
  1016. slapi_modify_internal_pb(&pb);
  1017. slapi_pblock_get(&pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
  1018. if (rc == LDAP_SUCCESS){
  1019. /*
  1020. ** Since we modified the acl
  1021. ** successfully, let's update the
  1022. ** in-memory acl list
  1023. */
  1024. slapi_pblock_set(&pb, SLAPI_TARGET_DN, (char*)slapi_sdn_get_dn(base) ); /* jcm: cast away const */
  1025. plugin_call_acl_mods_update (&pb, LDAP_REQ_MODIFY );
  1026. }
  1027. pblock_done(&pb);
  1028. }
  1029. }
  1030. be = slapi_get_next_backend (cookie);
  1031. }
  1032. slapi_ch_free((void **) &cookie);
  1033. }
  1034. void
  1035. add_password_attrs( Slapi_PBlock *pb, Operation *op, Slapi_Entry *e )
  1036. {
  1037. struct berval bv;
  1038. struct berval *bvals[2];
  1039. Slapi_Attr **a, **next;
  1040. passwdPolicy *pwpolicy = NULL;
  1041. char *dn = slapi_entry_get_ndn(e);
  1042. pwpolicy = new_passwdPolicy(pb, dn);
  1043. LDAPDebug( LDAP_DEBUG_TRACE, "add_password_attrs\n", 0, 0, 0 );
  1044. bvals[0] = &bv;
  1045. bvals[1] = NULL;
  1046. if ( pwpolicy->pw_must_change) {
  1047. /* must change password when first time logon */
  1048. bv.bv_val = format_genTime ( NO_TIME );
  1049. } else {
  1050. /* If passwordexpirationtime is specified by the user, don't
  1051. try to assign the initial value */
  1052. for ( a = &e->e_attrs; *a != NULL; a = next ) {
  1053. if ( strcasecmp( (*a)->a_type,
  1054. "passwordexpirationtime" ) == 0) {
  1055. delete_passwdPolicy(&pwpolicy);
  1056. return;
  1057. }
  1058. next = &(*a)->a_next;
  1059. }
  1060. bv.bv_val = format_genTime ( time_plus_sec ( current_time (),
  1061. pwpolicy->pw_maxage ) );
  1062. }
  1063. if ( pwpolicy->pw_exp || pwpolicy->pw_must_change ) {
  1064. bv.bv_len = strlen( bv.bv_val );
  1065. slapi_entry_attr_merge( e, "passwordexpirationtime", bvals );
  1066. }
  1067. slapi_ch_free((void **) &bv.bv_val );
  1068. /*
  1069. * If the password minimum age is not 0, calculate when the password
  1070. * is allowed to be changed again and store the result
  1071. * in passwordallowchangetime in the user's entry.
  1072. */
  1073. if ( pwpolicy->pw_minage != 0 ) {
  1074. bv.bv_val = format_genTime ( time_plus_sec ( current_time (),
  1075. pwpolicy->pw_minage ) );
  1076. bv.bv_len = strlen( bv.bv_val );
  1077. slapi_entry_attr_merge( e, "passwordallowchangetime", bvals );
  1078. slapi_ch_free((void **) &bv.bv_val );
  1079. }
  1080. delete_passwdPolicy(&pwpolicy);
  1081. }
  1082. static int
  1083. check_trivial_words (Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Value **vals, char *attrtype,
  1084. int toklen, Slapi_Mods *smods )
  1085. {
  1086. Slapi_Attr *attr = NULL;
  1087. Slapi_Mod *smodp = NULL, *smod = NULL;
  1088. Slapi_ValueSet *vs = NULL;
  1089. Slapi_Value *valp = NULL;
  1090. struct berval *bvp = NULL;
  1091. int i, pwresponse_req = 0;
  1092. vs = slapi_valueset_new();
  1093. slapi_pblock_get ( pb, SLAPI_PWPOLICY, &pwresponse_req );
  1094. /* Get a list of present values for attrtype in the existing entry, if there is one */
  1095. if (e != NULL )
  1096. {
  1097. if ( (attr = attrlist_find(e->e_attrs, attrtype)) &&
  1098. (!valueset_isempty(&attr->a_present_values)) )
  1099. {
  1100. /* Add present values to valueset */
  1101. slapi_attr_get_valueset( attr, &vs );
  1102. }
  1103. }
  1104. /* Get a list of new values for attrtype from the operation */
  1105. if ( (smod = slapi_mod_new()) && smods )
  1106. {
  1107. for (smodp = slapi_mods_get_first_smod(smods, smod);
  1108. smodp != NULL; smodp = slapi_mods_get_next_smod(smods, smod) )
  1109. {
  1110. /* Operation has new values for attrtype */
  1111. if ( PL_strcasecmp(attrtype, slapi_mod_get_type(smodp)) == 0 )
  1112. {
  1113. /* iterate through smodp values and add them if they don't exist */
  1114. for ( bvp = slapi_mod_get_first_value( smodp ); bvp != NULL;
  1115. bvp = slapi_mod_get_next_value( smodp ) )
  1116. {
  1117. /* Add new value to valueset */
  1118. valp = slapi_value_new_berval( bvp );
  1119. slapi_valueset_add_value_ext( vs, valp, SLAPI_VALUE_FLAG_PASSIN );
  1120. valp = NULL;
  1121. }
  1122. }
  1123. }
  1124. /* Free smod */
  1125. slapi_mod_free(&smod);
  1126. smod = NULL;
  1127. smodp = NULL;
  1128. }
  1129. /* If valueset isn't empty, we need to check if the password contains the values */
  1130. if ( slapi_valueset_count(vs) != 0 )
  1131. {
  1132. for ( i = slapi_valueset_first_value( vs, &valp);
  1133. (i != -1) && (valp != NULL);
  1134. i = slapi_valueset_next_value( vs, i, &valp) )
  1135. {
  1136. /* If the value is smaller than the max token length,
  1137. * we don't need to check the password */
  1138. if ( ldap_utf8characters(slapi_value_get_string( valp )) < toklen )
  1139. continue;
  1140. /* See if the password contains the value */
  1141. if ( PL_strcasestr( slapi_value_get_string( vals[0] ),
  1142. slapi_value_get_string( valp ) ) )
  1143. {
  1144. if ( pwresponse_req == 1 )
  1145. {
  1146. slapi_pwpolicy_make_response_control ( pb, -1, -1,
  1147. LDAP_PWPOLICY_INVALIDPWDSYNTAX );
  1148. }
  1149. pw_send_ldap_result ( pb,
  1150. LDAP_CONSTRAINT_VIOLATION, NULL,
  1151. "invalid password syntax", 0, NULL );
  1152. /* Free valueset */
  1153. slapi_valueset_free( vs );
  1154. return ( 1 );
  1155. }
  1156. }
  1157. }
  1158. /* Free valueset */
  1159. slapi_valueset_free( vs );
  1160. return ( 0 );
  1161. }
  1162. void
  1163. pw_add_allowchange_aci(Slapi_Entry *e, int pw_prohibit_change) {
  1164. char *aci_pw = NULL;
  1165. const char *aciattr = "aci";
  1166. aci_pw = slapi_ch_strdup(DENY_PW_CHANGE_ACI);
  1167. if (pw_prohibit_change) {
  1168. /* Add ACI */
  1169. slapi_entry_add_string(e, aciattr, aci_pw);
  1170. } else {
  1171. /* Remove ACI */
  1172. slapi_entry_delete_string(e, aciattr, aci_pw);
  1173. }
  1174. slapi_ch_free((void **) &aci_pw);
  1175. }
  1176. /* This function creates a passwdPolicy structure, loads it from either
  1177. * slapdFrontendconfig or the entry pointed by pwdpolicysubentry and
  1178. * returns the structure.
  1179. */
  1180. passwdPolicy *
  1181. new_passwdPolicy(Slapi_PBlock *pb, char *dn)
  1182. {
  1183. Slapi_ValueSet *values = NULL;
  1184. Slapi_Entry *e = NULL, *pw_entry = NULL;
  1185. int type_name_disposition = 0;
  1186. char *actual_type_name = NULL;
  1187. int attr_free_flags = 0;
  1188. int rc=0;
  1189. passwdPolicy *pwdpolicy = NULL;
  1190. Slapi_Attr *attr;
  1191. char *attr_name;
  1192. Slapi_Value **sval;
  1193. slapdFrontendConfig_t *slapdFrontendConfig;
  1194. Slapi_Operation *op;
  1195. char ebuf[ BUFSIZ ];
  1196. int optype = -1;
  1197. slapdFrontendConfig = getFrontendConfig();
  1198. pwdpolicy = (passwdPolicy *)slapi_ch_calloc(1, sizeof(passwdPolicy));
  1199. slapi_pblock_get( pb, SLAPI_OPERATION, &op);
  1200. slapi_pblock_get( pb, SLAPI_OPERATION_TYPE, &optype );
  1201. if (slapdFrontendConfig->pwpolicy_local == 1) {
  1202. if ( !operation_is_flag_set( op, OP_FLAG_INTERNAL ) && dn ) {
  1203. /* If we're doing an add, COS does not apply yet so we check
  1204. parents for the pwdpolicysubentry. We look only for virtual
  1205. attributes, because real ones are for single-target policy. */
  1206. if (optype == SLAPI_OPERATION_ADD) {
  1207. char *parentdn = slapi_ch_strdup(dn);
  1208. char *nextdn = NULL;
  1209. while ((nextdn = slapi_dn_parent( parentdn )) != NULL) {
  1210. if (((e = get_entry( pb, nextdn )) != NULL)) {
  1211. if ((slapi_vattr_values_get(e, "pwdpolicysubentry",
  1212. &values, &type_name_disposition, &actual_type_name,
  1213. SLAPI_VIRTUALATTRS_REQUEST_POINTERS |
  1214. SLAPI_VIRTUALATTRS_ONLY,
  1215. &attr_free_flags)) == 0) {
  1216. /* pwdpolicysubentry found! */
  1217. break;
  1218. } else {
  1219. /* Parent didn't have it, check grandparent... */
  1220. slapi_ch_free_string( &parentdn );
  1221. parentdn = nextdn;
  1222. slapi_entry_free( e );
  1223. e = NULL;
  1224. }
  1225. } else {
  1226. /* Reached the top without finding a pwdpolicysubentry. */
  1227. break;
  1228. }
  1229. }
  1230. slapi_ch_free_string( &parentdn );
  1231. slapi_ch_free_string( &nextdn );
  1232. /* If we're not doing an add, we look for the pwdpolicysubentry
  1233. attribute in the target entry itself. */
  1234. } else {
  1235. if ( (e = get_entry( pb, dn )) != NULL ) {
  1236. rc = slapi_vattr_values_get(e, "pwdpolicysubentry", &values,
  1237. &type_name_disposition, &actual_type_name,
  1238. SLAPI_VIRTUALATTRS_REQUEST_POINTERS, &attr_free_flags);
  1239. if (rc) {
  1240. values = NULL;
  1241. }
  1242. }
  1243. }
  1244. if (values != NULL) {
  1245. Slapi_Value *v = NULL;
  1246. const struct berval *bvp = NULL;
  1247. if ( ((rc = slapi_valueset_first_value( values, &v )) != -1) &&
  1248. ( bvp = slapi_value_get_berval( v )) != NULL ) {
  1249. if ( bvp != NULL ) {
  1250. /* we got the pwdpolicysubentry value */
  1251. pw_entry = get_entry ( pb, bvp->bv_val);
  1252. }
  1253. }
  1254. slapi_vattr_values_free(&values, &actual_type_name, attr_free_flags);
  1255. slapi_entry_free( e );
  1256. if ( pw_entry == NULL ) {
  1257. LDAPDebug(LDAP_DEBUG_ANY, "loading global password policy for %s"
  1258. "--local policy entry not found\n", escape_string(dn, ebuf),0,0);
  1259. goto done;
  1260. }
  1261. for (slapi_entry_first_attr(pw_entry, &attr); attr;
  1262. slapi_entry_next_attr(pw_entry, attr, &attr))
  1263. {
  1264. slapi_attr_get_type(attr, &attr_name);
  1265. if (!strcasecmp(attr_name, "passwordminage")) {
  1266. if ((sval = attr_get_present_values(attr))) {
  1267. pwdpolicy->pw_minage = slapi_value_get_long(*sval);
  1268. }
  1269. }
  1270. else
  1271. if (!strcasecmp(attr_name, "passwordmaxage")) {
  1272. if ((sval = attr_get_present_values(attr))) {
  1273. pwdpolicy->pw_maxage = slapi_value_get_long(*sval);
  1274. }
  1275. }
  1276. else
  1277. if (!strcasecmp(attr_name, "passwordwarning")) {
  1278. if ((sval = attr_get_present_values(attr))) {
  1279. pwdpolicy->pw_warning = slapi_value_get_long(*sval);
  1280. }
  1281. }
  1282. else
  1283. if (!strcasecmp(attr_name, "passwordhistory")) {
  1284. if ((sval = attr_get_present_values(attr))) {
  1285. pwdpolicy->pw_history =
  1286. pw_boolean_str2value(slapi_value_get_string(*sval));
  1287. }
  1288. }
  1289. else
  1290. if (!strcasecmp(attr_name, "passwordinhistory")) {
  1291. if ((sval = attr_get_present_values(attr))) {
  1292. pwdpolicy->pw_inhistory = slapi_value_get_int(*sval);
  1293. }
  1294. }
  1295. else
  1296. if (!strcasecmp(attr_name, "passwordlockout")) {
  1297. if ((sval = attr_get_present_values(attr))) {
  1298. pwdpolicy->pw_lockout =
  1299. pw_boolean_str2value(slapi_value_get_string(*sval));
  1300. }
  1301. }
  1302. else
  1303. if (!strcasecmp(attr_name, "passwordmaxfailure")) {
  1304. if ((sval = attr_get_present_values(attr))) {
  1305. pwdpolicy->pw_maxfailure = slapi_value_get_int(*sval);
  1306. }
  1307. }
  1308. else
  1309. if (!strcasecmp(attr_name, "passwordunlock")) {
  1310. if ((sval = attr_get_present_values(attr))) {
  1311. pwdpolicy->pw_unlock =
  1312. pw_boolean_str2value(slapi_value_get_string(*sval));
  1313. }
  1314. }
  1315. else
  1316. if (!strcasecmp(attr_name, "passwordlockoutduration")) {
  1317. if ((sval = attr_get_present_values(attr))) {
  1318. pwdpolicy->pw_lockduration = slapi_value_get_long(*sval);
  1319. }
  1320. }
  1321. else
  1322. if (!strcasecmp(attr_name, "passwordresetfailurecount")) {
  1323. if ((sval = attr_get_present_values(attr))) {
  1324. pwdpolicy->pw_resetfailurecount = slapi_value_get_long(*sval);
  1325. }
  1326. }
  1327. else
  1328. if (!strcasecmp(attr_name, "passwordchange")) {
  1329. if ((sval = attr_get_present_values(attr))) {
  1330. pwdpolicy->pw_change =
  1331. pw_boolean_str2value(slapi_value_get_string(*sval));
  1332. }
  1333. }
  1334. else
  1335. if (!strcasecmp(attr_name, "passwordmustchange")) {
  1336. if ((sval = attr_get_present_values(attr))) {
  1337. pwdpolicy->pw_must_change =
  1338. pw_boolean_str2value(slapi_value_get_string(*sval));
  1339. }
  1340. }
  1341. else
  1342. if (!strcasecmp(attr_name, "passwordchecksyntax")) {
  1343. if ((sval = attr_get_present_values(attr))) {
  1344. pwdpolicy->pw_syntax =
  1345. pw_boolean_str2value(slapi_value_get_string(*sval));
  1346. }
  1347. }
  1348. else
  1349. if (!strcasecmp(attr_name, "passwordminlength")) {
  1350. if ((sval = attr_get_present_values(attr))) {
  1351. pwdpolicy->pw_minlength = slapi_value_get_int(*sval);
  1352. }
  1353. }
  1354. else
  1355. if (!strcasecmp(attr_name, "passwordmindigits")) {
  1356. if ((sval = attr_get_present_values(attr))) {
  1357. pwdpolicy->pw_mindigits = slapi_value_get_int(*sval);
  1358. }
  1359. }
  1360. else
  1361. if (!strcasecmp(attr_name, "passwordminalphas")) {
  1362. if ((sval = attr_get_present_values(attr))) {
  1363. pwdpolicy->pw_minalphas = slapi_value_get_int(*sval);
  1364. }
  1365. }
  1366. else
  1367. if (!strcasecmp(attr_name, "passwordminuppers")) {
  1368. if ((sval = attr_get_present_values(attr))) {
  1369. pwdpolicy->pw_minuppers = slapi_value_get_int(*sval);
  1370. }
  1371. }
  1372. else
  1373. if (!strcasecmp(attr_name, "passwordminlowers")) {
  1374. if ((sval = attr_get_present_values(attr))) {
  1375. pwdpolicy->pw_minlowers = slapi_value_get_int(*sval);
  1376. }
  1377. }
  1378. else
  1379. if (!strcasecmp(attr_name, "passwordminspecials")) {
  1380. if ((sval = attr_get_present_values(attr))) {
  1381. pwdpolicy->pw_minspecials = slapi_value_get_int(*sval);
  1382. }
  1383. }
  1384. else
  1385. if (!strcasecmp(attr_name, "passwordmin8bit")) {
  1386. if ((sval = attr_get_present_values(attr))) {
  1387. pwdpolicy->pw_min8bit = slapi_value_get_int(*sval);
  1388. }
  1389. }
  1390. else
  1391. if (!strcasecmp(attr_name, "passwordmaxrepeats")) {
  1392. if ((sval = attr_get_present_values(attr))) {
  1393. pwdpolicy->pw_maxrepeats = slapi_value_get_int(*sval);
  1394. }
  1395. }
  1396. else
  1397. if (!strcasecmp(attr_name, "passwordmincategories")) {
  1398. if ((sval = attr_get_present_values(attr))) {
  1399. pwdpolicy->pw_mincategories = slapi_value_get_int(*sval);
  1400. }
  1401. }
  1402. else
  1403. if (!strcasecmp(attr_name, "passwordmintokenlength")) {
  1404. if ((sval = attr_get_present_values(attr))) {
  1405. pwdpolicy->pw_mintokenlength = slapi_value_get_int(*sval);
  1406. }
  1407. }
  1408. else
  1409. if (!strcasecmp(attr_name, "passwordexp")) {
  1410. if ((sval = attr_get_present_values(attr))) {
  1411. pwdpolicy->pw_exp =
  1412. pw_boolean_str2value(slapi_value_get_string(*sval));
  1413. }
  1414. }
  1415. else
  1416. if (!strcasecmp(attr_name, "passwordgracelimit")) {
  1417. if ((sval = attr_get_present_values(attr))) {
  1418. pwdpolicy->pw_gracelimit = slapi_value_get_int(*sval);
  1419. }
  1420. }
  1421. } /* end of for() loop */
  1422. if (pw_entry) {
  1423. slapi_entry_free(pw_entry);
  1424. }
  1425. return pwdpolicy;
  1426. } else if ( e ) {
  1427. slapi_entry_free( e );
  1428. }
  1429. }
  1430. }
  1431. done:
  1432. /* If we are here, that means we need to load the passwdPolicy
  1433. * structure from slapdFrontendconfig
  1434. */
  1435. *pwdpolicy = slapdFrontendConfig->pw_policy;
  1436. return pwdpolicy;
  1437. } /* End of new_passwdPolicy() */
  1438. void
  1439. delete_passwdPolicy( passwdPolicy **pwpolicy)
  1440. {
  1441. slapi_ch_free((void **)pwpolicy);
  1442. }
  1443. /*
  1444. * Encode the PWPOLICY RESPONSE control.
  1445. *
  1446. * Create a password policy response control,
  1447. * and add it to the PBlock to be returned to the client.
  1448. *
  1449. * Returns:
  1450. * success ( 0 )
  1451. * operationsError (1),
  1452. */
  1453. int
  1454. slapi_pwpolicy_make_response_control (Slapi_PBlock *pb, int seconds, int logins, ber_int_t error)
  1455. {
  1456. BerElement *ber= NULL;
  1457. struct berval *bvp = NULL;
  1458. int rc = -1;
  1459. /*
  1460. PasswordPolicyResponseValue ::= SEQUENCE {
  1461. warning [0] CHOICE OPTIONAL {
  1462. timeBeforeExpiration [0] INTEGER (0 .. maxInt),
  1463. graceLoginsRemaining [1] INTEGER (0 .. maxInt) }
  1464. error [1] ENUMERATED OPTIONAL {
  1465. passwordExpired (0),
  1466. accountLocked (1),
  1467. changeAfterReset (2),
  1468. passwordModNotAllowed (3),
  1469. mustSupplyOldPassword (4),
  1470. invalidPasswordSyntax (5),
  1471. passwordTooShort (6),
  1472. passwordTooYoung (7),
  1473. passwordInHistory (8) } }
  1474. */
  1475. LDAPDebug( LDAP_DEBUG_TRACE, "=> slapi_pwpolicy_make_response_control", 0, 0, 0 );
  1476. if ( ( ber = ber_alloc()) == NULL )
  1477. {
  1478. return rc;
  1479. }
  1480. rc = ber_printf( ber, "{" );
  1481. if ( seconds >= 0 || logins >= 0 ) {
  1482. if ( seconds >= 0 ) {
  1483. rc = ber_printf( ber, "t{ti}", LDAP_TAG_PWP_WARNING,
  1484. LDAP_TAG_PWP_SECSLEFT,
  1485. seconds );
  1486. }
  1487. else {
  1488. rc = ber_printf( ber, "t{ti}", LDAP_TAG_PWP_WARNING,
  1489. LDAP_TAG_PWP_GRCLOGINS,
  1490. logins );
  1491. }
  1492. }
  1493. if ( error >= 0 ) {
  1494. rc = ber_printf( ber, "te", LDAP_TAG_PWP_ERROR, error );
  1495. }
  1496. rc = ber_printf( ber, "}" );
  1497. if ( rc != -1 )
  1498. {
  1499. rc = ber_flatten( ber, &bvp );
  1500. }
  1501. ber_free( ber, 1 );
  1502. if ( rc != -1 )
  1503. {
  1504. LDAPControl new_ctrl = {0};
  1505. new_ctrl.ldctl_oid = LDAP_X_CONTROL_PWPOLICY_RESPONSE;
  1506. new_ctrl.ldctl_value = *bvp;
  1507. new_ctrl.ldctl_iscritical = 0;
  1508. rc= slapi_pblock_set( pb, SLAPI_ADD_RESCONTROL, &new_ctrl );
  1509. ber_bvfree(bvp);
  1510. }
  1511. LDAPDebug( LDAP_DEBUG_TRACE, "<= slapi_pwpolicy_make_response_control", 0, 0, 0 );
  1512. return (rc==-1?LDAP_OPERATIONS_ERROR:LDAP_SUCCESS);
  1513. }
  1514. static int
  1515. pw_boolean_str2value (const char *str)
  1516. {
  1517. if ( !strcasecmp(str, "true") ||
  1518. !strcasecmp(str, "on") ||
  1519. !strcasecmp(str, "1") ) {
  1520. return ( LDAP_ON );
  1521. }
  1522. if ( !strcasecmp(str, "false") ||
  1523. !strcasecmp(str, "off") ||
  1524. !strcasecmp(str, "0") ) {
  1525. return ( LDAP_OFF );
  1526. }
  1527. return (-1);
  1528. }
  1529. int
  1530. check_pw_minage_value( const char *attr_name, char *value, long minval, long maxval, char *errorbuf )
  1531. {
  1532. int retVal = LDAP_SUCCESS;
  1533. int age;
  1534. char *endPtr = NULL;
  1535. age = strtol(value, &endPtr, 0 );
  1536. if ( (age < 0) ||
  1537. (age > (MAX_ALLOWED_TIME_IN_SECS - current_time())) ||
  1538. (endPtr == NULL) || (endPtr == value) || !isdigit(*(endPtr-1)) )
  1539. {
  1540. PR_snprintf ( errorbuf, BUFSIZ,
  1541. "password minimum age \"%s\" seconds is invalid. ",
  1542. value );
  1543. retVal = LDAP_CONSTRAINT_VIOLATION;
  1544. }
  1545. return retVal;
  1546. }
  1547. int
  1548. check_pw_lockduration_value( const char *attr_name, char *value, long minval, long maxval, char *errorbuf )
  1549. {
  1550. int retVal = LDAP_SUCCESS;
  1551. long duration = 0; /* in minutes */
  1552. /* in seconds */
  1553. duration = strtol (value, NULL, 0);
  1554. if ( duration <= 0 || duration > (MAX_ALLOWED_TIME_IN_SECS - current_time()) ) {
  1555. PR_snprintf ( errorbuf, BUFSIZ,
  1556. "password lockout duration \"%s\" seconds is invalid. ",
  1557. value );
  1558. retVal = LDAP_CONSTRAINT_VIOLATION;
  1559. }
  1560. return retVal;
  1561. }
  1562. int
  1563. check_pw_resetfailurecount_value( const char *attr_name, char *value, long minval, long maxval, char *errorbuf )
  1564. {
  1565. int retVal = LDAP_SUCCESS;
  1566. long duration = 0; /* in minutes */
  1567. /* in seconds */
  1568. duration = strtol (value, NULL, 0);
  1569. if ( duration < 0 || duration > (MAX_ALLOWED_TIME_IN_SECS - current_time()) ) {
  1570. PR_snprintf ( errorbuf, BUFSIZ,
  1571. "password reset count duration \"%s\" seconds is invalid. ",
  1572. value );
  1573. retVal = LDAP_CONSTRAINT_VIOLATION;
  1574. }
  1575. return retVal;
  1576. }
  1577. int
  1578. check_pw_storagescheme_value( const char *attr_name, char *value, long minval, long maxval, char *errorbuf )
  1579. {
  1580. int retVal = LDAP_SUCCESS;
  1581. struct pw_scheme *new_scheme = NULL;
  1582. char * scheme_list = NULL;
  1583. scheme_list = plugin_get_pwd_storage_scheme_list(PLUGIN_LIST_PWD_STORAGE_SCHEME);
  1584. new_scheme = pw_name2scheme(value);
  1585. if ( new_scheme == NULL) {
  1586. if ( scheme_list != NULL ) {
  1587. PR_snprintf ( errorbuf, BUFSIZ,
  1588. "%s: invalid scheme - %s. Valid schemes are: %s",
  1589. CONFIG_PW_STORAGESCHEME_ATTRIBUTE, value, scheme_list );
  1590. } else {
  1591. PR_snprintf ( errorbuf, BUFSIZ,
  1592. "%s: invalid scheme - %s (no pwdstorage scheme"
  1593. " plugin loaded)",
  1594. CONFIG_PW_STORAGESCHEME_ATTRIBUTE, value);
  1595. }
  1596. retVal = LDAP_CONSTRAINT_VIOLATION;
  1597. }
  1598. else if ( new_scheme->pws_enc == NULL )
  1599. {
  1600. /* For example: the NS-MTA-MD5 password scheme is for comparision only
  1601. and for backward compatibility with an Old Messaging Server that was
  1602. setting passwords in the directory already encrypted. The scheme cannot
  1603. and won't encrypt passwords if they are in clear. We don't take it
  1604. */
  1605. if ( scheme_list != NULL ) {
  1606. PR_snprintf ( errorbuf, BUFSIZ,
  1607. "%s: invalid encoding scheme - %s\nValid values are: %s\n",
  1608. CONFIG_PW_STORAGESCHEME_ATTRIBUTE, value, scheme_list );
  1609. }
  1610. retVal = LDAP_CONSTRAINT_VIOLATION;
  1611. }
  1612. slapi_ch_free_string(&scheme_list);
  1613. return retVal;
  1614. }