pw.c 81 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755
  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) 2009 Red Hat, Inc.
  36. * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
  37. * All rights reserved.
  38. *
  39. * Contributors:
  40. * Hewlett-Packard Development Company, L.P.
  41. * Bugfix for bug #195302
  42. *
  43. * END COPYRIGHT BLOCK **/
  44. #ifdef HAVE_CONFIG_H
  45. # include <config.h>
  46. #endif
  47. /*
  48. * slapd hashed password routines
  49. *
  50. */
  51. #include <stdio.h>
  52. #include <string.h>
  53. #include <sys/types.h>
  54. #include <sechash.h>
  55. #if defined( _WIN32 )
  56. #undef DEBUG
  57. #endif /* _WIN32 */
  58. #if defined( _WIN32 )
  59. #undef LDAPDebug
  60. #endif /* _WIN32 */
  61. #if defined( USE_MOZLDAP )
  62. #define LDAP_MOD_OP (0x0007)
  63. #endif /* USE_MOZLDAP */
  64. #include "slap.h"
  65. #define DENY_PW_CHANGE_ACI "(targetattr = \"userPassword\") ( version 3.0; acl \"disallow_pw_change_aci\"; deny (write ) userdn = \"ldap:///self\";)"
  66. #define GENERALIZED_TIME_LENGTH 15
  67. static int pw_in_history(Slapi_Value **history_vals, const Slapi_Value *pw_val);
  68. static int update_pw_history( Slapi_PBlock *pb, const Slapi_DN *sdn, char *old_pw );
  69. static int check_trivial_words (Slapi_PBlock *, Slapi_Entry *, Slapi_Value **,
  70. char *attrtype, int toklen, Slapi_Mods *smods );
  71. static int pw_boolean_str2value (const char *str);
  72. /* static LDAPMod* pw_malloc_mod (char* name, char* value, int mod_op); */
  73. static void pw_get_admin_users(passwdPolicy *pwp);
  74. /*
  75. * We want to be able to return errors to internal operations (which
  76. * can come from the password change extended operation). So we have
  77. * a special result function that does the right thing for an internal op.
  78. */
  79. static void
  80. pw_send_ldap_result(
  81. Slapi_PBlock *pb,
  82. int err,
  83. char *matched,
  84. char *text,
  85. int nentries,
  86. struct berval **urls
  87. )
  88. {
  89. int internal_op = 0;
  90. Slapi_Operation *operation = NULL;
  91. slapi_pblock_get (pb, SLAPI_OPERATION, &operation);
  92. internal_op= operation_is_flag_set(operation, OP_FLAG_INTERNAL);
  93. if (internal_op) {
  94. slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_RESULT, &err);
  95. } else {
  96. send_ldap_result(pb, err, matched, text, nentries, urls);
  97. }
  98. }
  99. /*
  100. * Like slapi_value_find, except for passwords.
  101. * returns 0 if password "v" is found in "vals"; non-zero otherwise
  102. */
  103. SLAPI_DEPRECATED int
  104. slapi_pw_find(
  105. struct berval **vals,
  106. struct berval *v
  107. )
  108. {
  109. int rc;
  110. Slapi_Value **svin_vals= NULL;
  111. Slapi_Value svin_v;
  112. slapi_value_init_berval(&svin_v,v);
  113. valuearray_init_bervalarray(vals,&svin_vals); /* JCM SLOW FUNCTION */
  114. rc= slapi_pw_find_sv(svin_vals,&svin_v);
  115. valuearray_free(&svin_vals);
  116. value_done(&svin_v);
  117. return rc;
  118. }
  119. /*
  120. * Like slapi_value_find, except for passwords.
  121. * returns 0 if password "v" is found in "vals"; non-zero otherwise
  122. */
  123. int
  124. slapi_pw_find_sv(
  125. Slapi_Value **vals,
  126. const Slapi_Value *v
  127. )
  128. {
  129. struct pw_scheme *pwsp;
  130. char *valpwd;
  131. int i;
  132. LDAPDebug( LDAP_DEBUG_TRACE, "=> slapi_pw_find value: \"%s\"\n", slapi_value_get_string(v), 0, 0 ); /* JCM Innards */
  133. for ( i = 0; vals[i] != NULL; i++ )
  134. {
  135. pwsp = pw_val2scheme( (char*)slapi_value_get_string(vals[i]), &valpwd, 1 ); /* JCM Innards*/
  136. if ( pwsp != NULL &&
  137. (*(pwsp->pws_cmp))( (char*)slapi_value_get_string(v), valpwd ) == 0 ) /* JCM Innards*/
  138. {
  139. LDAPDebug( LDAP_DEBUG_TRACE,
  140. "<= slapi_pw_find matched \"%s\" using scheme \"%s\"\n",
  141. valpwd, pwsp->pws_name, 0 );
  142. free_pw_scheme( pwsp );
  143. return( 0 ); /* found it */
  144. }
  145. free_pw_scheme( pwsp );
  146. }
  147. LDAPDebug( LDAP_DEBUG_TRACE, "<= slapi_pw_find no matching password\n", 0, 0, 0 );
  148. return( 1 ); /* no match */
  149. }
  150. /* Checks if the specified value is encoded.
  151. Returns 1 if it is and 0 otherwise
  152. */
  153. int slapi_is_encoded (char *value)
  154. {
  155. struct pw_scheme *is_hashed = NULL;
  156. int is_encoded = 0;
  157. is_hashed = pw_val2scheme ( value, NULL, 0 );
  158. if ( is_hashed != NULL )
  159. {
  160. free_pw_scheme( is_hashed );
  161. is_encoded = 1;
  162. }
  163. return (is_encoded);
  164. }
  165. char* slapi_encode (char *value, char *alg)
  166. {
  167. return( slapi_encode_ext( NULL, NULL, value, alg ) );
  168. }
  169. char* slapi_encode_ext (Slapi_PBlock *pb, const Slapi_DN *sdn, char *value, char *alg)
  170. {
  171. struct pw_scheme *enc_scheme = NULL;
  172. char *(*pws_enc) ( char *pwd ) = NULL;
  173. char *hashedval = NULL;
  174. passwdPolicy *pwpolicy=NULL;
  175. if (alg == NULL) /* use local scheme, or global if we can't fetch local */
  176. {
  177. pwpolicy = new_passwdPolicy(pb, (char*)slapi_sdn_get_ndn(sdn) );
  178. pws_enc = pwpolicy->pw_storagescheme->pws_enc;
  179. if (pws_enc == NULL)
  180. {
  181. slapi_log_error( SLAPI_LOG_FATAL, NULL,
  182. "slapi_encode: no server scheme\n" );
  183. return NULL;
  184. }
  185. }
  186. else
  187. {
  188. enc_scheme = pw_name2scheme(alg);
  189. if ( enc_scheme == NULL)
  190. {
  191. char * scheme_list = plugin_get_pwd_storage_scheme_list(PLUGIN_LIST_PWD_STORAGE_SCHEME);
  192. if ( scheme_list != NULL ) {
  193. slapi_log_error( SLAPI_LOG_FATAL, NULL,
  194. "slapi_encode: invalid scheme - %s\n"
  195. "Valid values are: %s\n", alg, scheme_list );
  196. slapi_ch_free((void **)&scheme_list);
  197. } else {
  198. slapi_log_error( SLAPI_LOG_FATAL, NULL,
  199. "slapi_encode: invalid scheme - %s\n"
  200. "no pwdstorage scheme plugin loaded", alg);
  201. }
  202. return NULL;
  203. }
  204. pws_enc = enc_scheme->pws_enc;
  205. free_pw_scheme(enc_scheme);
  206. }
  207. hashedval = (*pws_enc)(value);
  208. return hashedval;
  209. }
  210. /*
  211. * Return a pointer to the pw_scheme struct for scheme "name"
  212. * NULL is returned is no matching scheme is found.
  213. */
  214. struct pw_scheme *
  215. pw_name2scheme( char *name )
  216. {
  217. struct pw_scheme *pwsp;
  218. struct slapdplugin *p;
  219. if ( (p = plugin_get_pwd_storage_scheme(name, strlen(name), PLUGIN_LIST_PWD_STORAGE_SCHEME)) != NULL ) {
  220. pwsp = (struct pw_scheme *) slapi_ch_malloc (sizeof(struct pw_scheme));
  221. if ( pwsp != NULL ) {
  222. typedef int (*CMPFP)(char *, char *);
  223. typedef char * (*ENCFP)(char *);
  224. pwsp->pws_name = slapi_ch_strdup( p->plg_pwdstorageschemename );
  225. pwsp->pws_cmp = (CMPFP)p->plg_pwdstorageschemecmp;
  226. pwsp->pws_enc = (ENCFP)p->plg_pwdstorageschemeenc;
  227. pwsp->pws_len = strlen(pwsp->pws_name) ;
  228. return(pwsp);
  229. }
  230. }
  231. return( NULL );
  232. }
  233. void free_pw_scheme(struct pw_scheme *pwsp)
  234. {
  235. if ( pwsp != NULL )
  236. {
  237. slapi_ch_free( (void**)&pwsp->pws_name );
  238. slapi_ch_free( (void**)&pwsp );
  239. }
  240. }
  241. /*
  242. * Return the password scheme for value "val". This is determined by
  243. * checking "val" against our scheme prefixes.
  244. *
  245. * If "valpwdp" is not NULL, it is set to point to the value with any
  246. * prefix removed.
  247. *
  248. * If no matching scheme is found and first_is_default is non-zero, the
  249. * first scheme is returned. If no matching scheme is found and
  250. * first_is_default is zero, NULL is returned.
  251. */
  252. struct pw_scheme *
  253. pw_val2scheme( char *val, char **valpwdp, int first_is_default )
  254. {
  255. struct pw_scheme *pwsp;
  256. int namelen, prefixlen;
  257. char *end, buf[ PWD_MAX_NAME_LEN + 1 ];
  258. if ( *val != PWD_HASH_PREFIX_START ||
  259. ( end = strchr( val, PWD_HASH_PREFIX_END )) == NULL ||
  260. ( namelen = end - val - 1 ) > PWD_MAX_NAME_LEN ) {
  261. if ( !first_is_default ) {
  262. return( NULL );
  263. }
  264. pwsp = pw_name2scheme("CLEAR"); /* default to first scheme */
  265. prefixlen = 0;
  266. } else {
  267. memcpy( buf, val + 1, namelen );
  268. buf[ namelen ] = '\0';
  269. pwsp = pw_name2scheme(buf);
  270. if ( pwsp == NULL ) {
  271. if ( !first_is_default ) {
  272. return( NULL );
  273. }
  274. pwsp = pw_name2scheme("CLEAR");
  275. prefixlen = 0;
  276. } else {
  277. prefixlen = pwsp->pws_len + 2;
  278. }
  279. }
  280. if ( valpwdp != NULL ) {
  281. *valpwdp = val + prefixlen;
  282. }
  283. return( pwsp );
  284. }
  285. /*
  286. * re-encode the password values in "vals" using a hashing algorithm
  287. * vals[n] is assumed to be an alloc'd Slapi_Value that can be free'd and
  288. * replaced. If a value is already encoded, we do not re-encode it.
  289. * Return 0 if all goes well and < 0 if an error occurs.
  290. */
  291. int
  292. pw_encodevals( Slapi_Value **vals )
  293. {
  294. return( pw_encodevals_ext( NULL, NULL, vals ) );
  295. }
  296. /*
  297. * Same as pw_encodevals, except if a pb and sdn are passed in, we will try
  298. * to check the password scheme specified by local password policy.
  299. */
  300. int
  301. pw_encodevals_ext( Slapi_PBlock *pb, const Slapi_DN *sdn, Slapi_Value **vals )
  302. {
  303. int i;
  304. passwdPolicy *pwpolicy=NULL;
  305. char *(*pws_enc) ( char *pwd ) = NULL;
  306. if ( (NULL == pb) || (NULL == vals) ) {
  307. return( 0 );
  308. }
  309. /* new_passwdPolicy gives us a local policy if sdn and pb are set and
  310. can be used to find a local policy, else we get the global policy */
  311. pwpolicy = new_passwdPolicy(pb, sdn ? (char*)slapi_sdn_get_ndn(sdn) : NULL);
  312. if (pwpolicy) {
  313. if (pwpolicy->pw_storagescheme) {
  314. pws_enc = pwpolicy->pw_storagescheme->pws_enc;
  315. }
  316. }
  317. /* Password scheme encryption function was not found */
  318. if ( pws_enc == NULL ) {
  319. return( 0 );
  320. }
  321. for ( i = 0; vals[ i ] != NULL; ++i ) {
  322. struct pw_scheme *pwsp = NULL;
  323. char *enc = NULL;
  324. if ( (pwsp=pw_val2scheme( (char*)slapi_value_get_string(vals[ i ]), NULL, 0)) != NULL ) { /* JCM Innards */
  325. /* If the value already specifies clear storage, call the
  326. * clear storage plug-in */
  327. if (strcasecmp( pwsp->pws_name, "clear" ) == 0) {
  328. enc = (*pwsp->pws_enc)( (char*)slapi_value_get_string(vals[ i ]) );
  329. } else {
  330. free_pw_scheme( pwsp );
  331. continue; /* don't touch pre-encoded values */
  332. }
  333. }
  334. free_pw_scheme( pwsp );
  335. if ((!enc) && (( enc = (*pws_enc)( (char*)slapi_value_get_string(vals[ i ]) )) == NULL )) {
  336. return( -1 );
  337. }
  338. slapi_value_free(&vals[ i ]);
  339. vals[ i ] = slapi_value_new_string_passin(enc);
  340. }
  341. return( 0 );
  342. }
  343. /*
  344. * Check if the prefix of the cipher is the one that is supposed to be
  345. * Extract from the whole cipher the encrypted password (remove the prefix)
  346. */
  347. int checkPrefix(char *cipher, char *schemaName, char **encrypt)
  348. {
  349. int namelen;
  350. /* buf contains the extracted schema name */
  351. char *end, buf[ 3*PWD_MAX_NAME_LEN + 1 ];
  352. if ( (*cipher == PWD_HASH_PREFIX_START) &&
  353. ((end = strchr(cipher, PWD_HASH_PREFIX_END)) != NULL) &&
  354. ((namelen = end - cipher - 1 ) <= (3*PWD_MAX_NAME_LEN)) )
  355. {
  356. memcpy( buf, cipher + 1, namelen );
  357. buf[ namelen ] = '\0';
  358. if ( strcasecmp( buf, schemaName) != 0 )
  359. {
  360. /* schema names are different, error */
  361. return 1;
  362. }
  363. else
  364. {
  365. /* extract the encrypted password */
  366. *encrypt = cipher + strlen(schemaName) + 2;
  367. return 0;
  368. }
  369. }
  370. /* cipher is not prefixed, already in clear ? */
  371. return -1;
  372. }
  373. /*
  374. * Decode the attribute "attr_name" with one of the reversible encryption mechanism
  375. * Returns -1 on error
  376. * Returns 0 on success with strdup'ed plain
  377. * Returns 1 on success with *plain=cipher
  378. */
  379. int
  380. pw_rever_decode(char *cipher, char **plain, const char * attr_name)
  381. {
  382. struct pw_scheme *pwsp = NULL;
  383. struct slapdplugin *p = NULL;
  384. int ret_code = 1;
  385. for ( p = get_plugin_list(PLUGIN_LIST_REVER_PWD_STORAGE_SCHEME); p != NULL; p = p->plg_next )
  386. {
  387. char *L_attr = NULL;
  388. int i = 0;
  389. char *encrypt = NULL;
  390. int prefixOK = -1;
  391. /* Get the appropriate decoding function */
  392. for ( L_attr = p->plg_argv[i]; i<p->plg_argc; L_attr = p->plg_argv[++i] )
  393. {
  394. if (slapi_attr_types_equivalent(L_attr, attr_name))
  395. {
  396. typedef char * (*ENCFP)(char *);
  397. pwsp = (struct pw_scheme *) slapi_ch_calloc (1, sizeof(struct pw_scheme));
  398. pwsp->pws_dec = (ENCFP)p->plg_pwdstorageschemedec;
  399. pwsp->pws_name = slapi_ch_strdup( p->plg_pwdstorageschemename );
  400. pwsp->pws_len = strlen(pwsp->pws_name) ;
  401. if ( pwsp->pws_dec != NULL )
  402. {
  403. /* check that the prefix of the cipher is the same name
  404. as the scheme name */
  405. prefixOK = checkPrefix(cipher, pwsp->pws_name, &encrypt);
  406. if ( prefixOK == -1 )
  407. {
  408. /* no prefix, already in clear ? */
  409. *plain = cipher;
  410. ret_code = 1;
  411. goto free_and_return;
  412. }
  413. else if ( prefixOK == 1 )
  414. {
  415. /* scheme names are different */
  416. ret_code = -1;
  417. goto free_and_return;
  418. }
  419. else
  420. {
  421. if ( ( *plain = (pwsp->pws_dec)( encrypt )) == NULL )
  422. {
  423. /* pb during decoding */
  424. ret_code = -1;
  425. goto free_and_return;
  426. }
  427. /* decoding is OK */
  428. ret_code = 0;
  429. goto free_and_return;
  430. }
  431. }
  432. free_pw_scheme( pwsp );
  433. pwsp = NULL;
  434. }
  435. }
  436. }
  437. free_and_return:
  438. if ( pwsp != NULL )
  439. {
  440. free_pw_scheme( pwsp );
  441. }
  442. return(ret_code);
  443. }
  444. /*
  445. * Encode the attribute "attr_name" with one of the reversible encryption mechanism
  446. */
  447. int
  448. pw_rever_encode(Slapi_Value **vals, char * attr_name)
  449. {
  450. char *enc;
  451. struct pw_scheme *pwsp = NULL;
  452. struct slapdplugin *p;
  453. if (vals == NULL){
  454. return (0);
  455. }
  456. for ( p = get_plugin_list(PLUGIN_LIST_REVER_PWD_STORAGE_SCHEME); p != NULL; p = p->plg_next )
  457. {
  458. char *L_attr = NULL;
  459. int i = 0;
  460. /* Get the appropriate encoding function */
  461. for ( L_attr = p->plg_argv[i]; i<p->plg_argc; L_attr = p->plg_argv[++i] )
  462. {
  463. if (slapi_attr_types_equivalent(L_attr, attr_name))
  464. {
  465. typedef char * (*ENCFP)(char *);
  466. pwsp = (struct pw_scheme *) slapi_ch_calloc (1, sizeof(struct pw_scheme));
  467. pwsp->pws_enc = (ENCFP)p->plg_pwdstorageschemeenc;
  468. pwsp->pws_name = slapi_ch_strdup( p->plg_pwdstorageschemename );
  469. if ( pwsp->pws_enc != NULL )
  470. {
  471. for ( i = 0; vals[i] != NULL; ++i )
  472. {
  473. char *encrypt = NULL;
  474. int prefixOK;
  475. prefixOK = checkPrefix((char*)slapi_value_get_string(vals[i]),
  476. pwsp->pws_name,
  477. &encrypt);
  478. if ( prefixOK == 0 )
  479. {
  480. /* Don't touch already encoded value */
  481. continue; /* don't touch pre-encoded values */
  482. }
  483. else if (prefixOK == 1 )
  484. {
  485. /* credential is already encoded, but not with this schema. Error */
  486. free_pw_scheme( pwsp );
  487. return( -1 );
  488. }
  489. if ( ( enc = (pwsp->pws_enc)( (char*)slapi_value_get_string(vals[ i ]) )) == NULL )
  490. {
  491. free_pw_scheme( pwsp );
  492. return( -1 );
  493. }
  494. slapi_value_free(&vals[ i ]);
  495. vals[ i ] = slapi_value_new_string_passin(enc);
  496. free_pw_scheme( pwsp );
  497. return (0);
  498. }
  499. }
  500. free_pw_scheme( pwsp );
  501. }
  502. }
  503. }
  504. return(-1);
  505. }
  506. /* ONREPL - below are the functions moved from pw_mgmt.c.
  507. this is done to allow the functions to be used
  508. by functions linked into libslapd.
  509. */
  510. /* update_pw_info is called after password is modified successfully */
  511. /* it should update passwordHistory, and passwordExpirationTime */
  512. /* SLAPI_ENTRY_POST_OP must be set */
  513. int
  514. update_pw_info ( Slapi_PBlock *pb , char *old_pw)
  515. {
  516. Slapi_Operation *operation = NULL;
  517. Slapi_Entry *e = NULL;
  518. Slapi_DN *sdn = NULL;
  519. Slapi_Mods smods;
  520. passwdPolicy *pwpolicy = NULL;
  521. time_t pw_exp_date;
  522. time_t cur_time;
  523. const char *target_dn, *bind_dn;
  524. char *timestr;
  525. int internal_op = 0;
  526. slapi_pblock_get( pb, SLAPI_OPERATION, &operation);
  527. slapi_pblock_get( pb, SLAPI_TARGET_SDN, &sdn );
  528. slapi_pblock_get( pb, SLAPI_REQUESTOR_NDN, &bind_dn);
  529. slapi_pblock_get( pb, SLAPI_ENTRY_PRE_OP, &e);
  530. internal_op = slapi_operation_is_flag_set(operation, SLAPI_OP_FLAG_INTERNAL);
  531. target_dn = slapi_sdn_get_ndn(sdn);
  532. pwpolicy = new_passwdPolicy(pb, target_dn);
  533. cur_time = current_time();
  534. slapi_mods_init(&smods, 0);
  535. /* update passwordHistory */
  536. if ( old_pw != NULL && pwpolicy->pw_history == 1 ) {
  537. update_pw_history(pb, sdn, old_pw);
  538. slapi_ch_free ( (void**)&old_pw );
  539. }
  540. /* Update the "pwdUpdateTime" attribute */
  541. if ( pwpolicy->pw_track_update_time ){
  542. timestr = format_genTime(cur_time);
  543. slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "pwdUpdateTime",timestr);
  544. slapi_ch_free((void **)&timestr);
  545. }
  546. /* update password allow change time */
  547. if ( pwpolicy->pw_minage != 0) {
  548. timestr = format_genTime( time_plus_sec( cur_time, pwpolicy->pw_minage ));
  549. slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordAllowChangeTime", timestr);
  550. slapi_ch_free((void **)&timestr);
  551. }
  552. /*
  553. * Fix for Bug 560707
  554. * Removed the restriction that the lock variables (retry count) will
  555. * be set only when root resets the password.
  556. * Now admins will also have these privileges.
  557. */
  558. if (pwpolicy->pw_lockout) {
  559. set_retry_cnt_mods (pb, &smods, 0 );
  560. }
  561. if(!slapi_entry_attr_hasvalue(e,"passwordgraceusertime", "0")){
  562. /* Clear the passwordgraceusertime from the user entry */
  563. slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordgraceusertime", "0");
  564. }
  565. /*
  566. * If the password is reset by a different user, mark it the first time logon. If this is an internal
  567. * operation, we have a special case for the password modify extended operation where
  568. * we stuff the actual user who initiated the password change in pb_conn. We check
  569. * for this special case to ensure we reset the expiration date properly.
  570. */
  571. if ((internal_op && pwpolicy->pw_must_change && (!pb->pb_conn || strcasecmp(target_dn, pb->pb_conn->c_dn))) ||
  572. (!internal_op && pwpolicy->pw_must_change &&
  573. ((target_dn && bind_dn && strcasecmp(target_dn, bind_dn)) && pw_is_pwp_admin(pb, pwpolicy))))
  574. {
  575. pw_exp_date = NO_TIME;
  576. } else if ( pwpolicy->pw_exp == 1 ) {
  577. Slapi_Entry *pse = NULL;
  578. /* update password expiration date */
  579. pw_exp_date = time_plus_sec ( cur_time, pwpolicy->pw_maxage );
  580. slapi_pblock_get(pb,SLAPI_ENTRY_POST_OP,&pse);
  581. if (pse) {
  582. char *prev_exp_date_str;
  583. /*
  584. * if the password expiry time is SLAPD_END_TIME,
  585. * don't roll it back
  586. */
  587. prev_exp_date_str = slapi_entry_attr_get_charptr(pse,"passwordExpirationTime");
  588. if (prev_exp_date_str) {
  589. time_t prev_exp_date;
  590. prev_exp_date = parse_genTime(prev_exp_date_str);
  591. if (prev_exp_date == NO_TIME || prev_exp_date == NOT_FIRST_TIME) {
  592. /* ignore as will replace */
  593. } else if (prev_exp_date == SLAPD_END_TIME) {
  594. /* Special entries' passwords never expire */
  595. slapi_ch_free((void**)&prev_exp_date_str);
  596. pw_apply_mods(sdn, &smods);
  597. slapi_mods_done(&smods);
  598. return 0;
  599. }
  600. slapi_ch_free((void**)&prev_exp_date_str);
  601. }
  602. } /* post op entry */
  603. } else if (pwpolicy->pw_must_change) {
  604. /*
  605. * pw is not changed by root, and must change pw first time
  606. * log on
  607. */
  608. pw_exp_date = NOT_FIRST_TIME;
  609. } else {
  610. pw_apply_mods(sdn, &smods);
  611. slapi_mods_done(&smods);
  612. return 0;
  613. }
  614. timestr = format_genTime ( pw_exp_date );
  615. slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordExpirationTime", timestr);
  616. slapi_ch_free((void **)&timestr);
  617. slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "passwordExpWarned", "0");
  618. pw_apply_mods(sdn, &smods);
  619. slapi_mods_done(&smods);
  620. if (pb->pb_conn) { /* no conn for internal op */
  621. /* reset c_needpw to 0 */
  622. pb->pb_conn->c_needpw = 0;
  623. }
  624. return 0;
  625. }
  626. int
  627. check_pw_minage ( Slapi_PBlock *pb, const Slapi_DN *sdn, struct berval **vals)
  628. {
  629. char *dn= (char*)slapi_sdn_get_ndn(sdn); /* jcm - Had to cast away const */
  630. passwdPolicy *pwpolicy=NULL;
  631. int pwresponse_req = 0;
  632. pwpolicy = new_passwdPolicy(pb, dn);
  633. slapi_pblock_get ( pb, SLAPI_PWPOLICY, &pwresponse_req );
  634. if ( !pb->pb_op->o_isroot &&
  635. pwpolicy->pw_minage != 0 ) {
  636. Slapi_Entry *e;
  637. char *passwordAllowChangeTime;
  638. /* retrieve the entry */
  639. e = get_entry ( pb, dn );
  640. if ( e == NULL ) {
  641. return ( -1 );
  642. }
  643. /* get passwordAllowChangeTime attribute */
  644. passwordAllowChangeTime= slapi_entry_attr_get_charptr(e, "passwordAllowChangeTime");
  645. if (passwordAllowChangeTime!=NULL)
  646. {
  647. time_t pw_allowchange_date;
  648. char *cur_time_str = NULL;
  649. pw_allowchange_date = parse_genTime(passwordAllowChangeTime);
  650. slapi_ch_free((void **) &passwordAllowChangeTime );
  651. /* check if allow to change the password */
  652. cur_time_str = format_genTime ( current_time() );
  653. if ( difftime ( pw_allowchange_date,
  654. parse_genTime ( cur_time_str )) > 0 )
  655. {
  656. if ( pwresponse_req == 1 ) {
  657. slapi_pwpolicy_make_response_control ( pb, -1, -1,
  658. LDAP_PWPOLICY_PWDTOOYOUNG );
  659. }
  660. pw_send_ldap_result ( pb,
  661. LDAP_CONSTRAINT_VIOLATION, NULL,
  662. "within password minimum age", 0, NULL );
  663. slapi_entry_free( e );
  664. slapi_ch_free((void **) &cur_time_str );
  665. return ( 1 );
  666. }
  667. slapi_ch_free((void **) &cur_time_str );
  668. }
  669. slapi_entry_free( e );
  670. }
  671. return ( 0 );
  672. }
  673. /* check_pw_syntax is called before add or modify operation on userpassword attribute*/
  674. int
  675. check_pw_syntax ( Slapi_PBlock *pb, const Slapi_DN *sdn, Slapi_Value **vals,
  676. char **old_pw, Slapi_Entry *e, int mod_op)
  677. {
  678. return ( check_pw_syntax_ext(pb, sdn, vals, old_pw, e, mod_op, NULL) );
  679. }
  680. int
  681. check_pw_syntax_ext ( Slapi_PBlock *pb, const Slapi_DN *sdn, Slapi_Value **vals,
  682. char **old_pw, Slapi_Entry *e, int mod_op, Slapi_Mods *smods)
  683. {
  684. Slapi_Attr *attr;
  685. int i, pwresponse_req = 0;
  686. int is_replication = 0;
  687. int internal_op = 0;
  688. char *dn= (char*)slapi_sdn_get_ndn(sdn); /* jcm - Had to cast away const */
  689. char *pwd = NULL;
  690. char *p = NULL;
  691. char errormsg[ BUFSIZ ];
  692. passwdPolicy *pwpolicy = NULL;
  693. Slapi_Operation *operation = NULL;
  694. /*
  695. * check_pw_syntax_ext could be called with mod_op == LDAP_MOD_DELETE.
  696. * In that case, no need to check the password syntax, but just returns
  697. * PASS == 0.
  698. */
  699. if (LDAP_MOD_DELETE == (mod_op & LDAP_MOD_OP)) {
  700. /* check if the entry exists or not */
  701. e = get_entry(pb, dn);
  702. if (e == NULL) {
  703. return -1;
  704. }
  705. slapi_entry_free(e);
  706. return 0;
  707. }
  708. if (NULL == vals) {
  709. slapi_log_error( SLAPI_LOG_FATAL, NULL,
  710. "check_pw_syntax_ext: no passwords to check\n" );
  711. return -1;
  712. }
  713. pwpolicy = new_passwdPolicy(pb, dn);
  714. slapi_pblock_get ( pb, SLAPI_PWPOLICY, &pwresponse_req );
  715. slapi_pblock_get(pb, SLAPI_IS_REPLICATED_OPERATION, &is_replication);
  716. slapi_pblock_get(pb, SLAPI_OPERATION, &operation);
  717. internal_op = slapi_operation_is_flag_set(operation, SLAPI_OP_FLAG_INTERNAL);
  718. /*
  719. * Check if password is already hashed and reject if so. We need to
  720. * allow the root DN, password admins, and replicated ops to send
  721. * pre-hashed passwords. We also check for a connection object
  722. * when processing an internal operation to handle a special
  723. * case for the password modify extended operation.
  724. */
  725. for ( i = 0; vals[ i ] != NULL; ++i ){
  726. if (slapi_is_encoded((char *)slapi_value_get_string(vals[i]))) {
  727. if (!is_replication && !config_get_allow_hashed_pw() &&
  728. ((internal_op && pb->pb_conn && !slapi_dn_isroot(pb->pb_conn->c_dn)) ||
  729. (!internal_op && !pw_is_pwp_admin(pb, pwpolicy)))) {
  730. PR_snprintf( errormsg, BUFSIZ,
  731. "invalid password syntax - passwords with storage scheme are not allowed");
  732. if ( pwresponse_req == 1 ) {
  733. slapi_pwpolicy_make_response_control ( pb, -1, -1,
  734. LDAP_PWPOLICY_INVALIDPWDSYNTAX );
  735. }
  736. pw_send_ldap_result ( pb, LDAP_CONSTRAINT_VIOLATION, NULL, errormsg, 0, NULL );
  737. return( 1 );
  738. } else {
  739. /* We want to skip syntax checking since this is a pre-hashed password */
  740. return( 0 );
  741. }
  742. }
  743. }
  744. if ( pwpolicy->pw_syntax == 1 ) {
  745. for ( i = 0; vals[ i ] != NULL; ++i ) {
  746. int syntax_violation = 0;
  747. int num_digits = 0;
  748. int num_alphas = 0;
  749. int num_uppers = 0;
  750. int num_lowers = 0;
  751. int num_specials = 0;
  752. int num_8bit = 0;
  753. int num_repeated = 0;
  754. int max_repeated = 0;
  755. int num_categories = 0;
  756. /* check for the minimum password length */
  757. if ( pwpolicy->pw_minlength >
  758. ldap_utf8characters((char *)slapi_value_get_string( vals[i] )) )
  759. {
  760. PR_snprintf( errormsg, BUFSIZ,
  761. "invalid password syntax - password must be at least %d characters long",
  762. pwpolicy->pw_minlength );
  763. if ( pwresponse_req == 1 ) {
  764. slapi_pwpolicy_make_response_control ( pb, -1, -1,
  765. LDAP_PWPOLICY_PWDTOOSHORT );
  766. }
  767. pw_send_ldap_result ( pb, LDAP_CONSTRAINT_VIOLATION, NULL, errormsg, 0, NULL );
  768. return ( 1 );
  769. }
  770. /* check character types */
  771. pwd = (char *)slapi_value_get_string( vals[i] );
  772. p = pwd;
  773. while ( p && *p )
  774. {
  775. if ( ldap_utf8isdigit( p ) ) {
  776. num_digits++;
  777. } else if ( ldap_utf8isalpha( p ) ) {
  778. num_alphas++;
  779. if ( slapi_utf8isLower( (unsigned char *)p ) ) {
  780. num_lowers++;
  781. } else {
  782. num_uppers++;
  783. }
  784. } else {
  785. /* check if this is an 8-bit char */
  786. if ( *p & 128 ) {
  787. num_8bit++;
  788. } else {
  789. num_specials++;
  790. }
  791. }
  792. /* check for repeating characters. If this is the
  793. first char of the password, no need to check */
  794. if ( pwd != p ) {
  795. int len = ldap_utf8len( p );
  796. char *prev_p = ldap_utf8prev( p );
  797. if ( len == ldap_utf8len( prev_p ) )
  798. {
  799. if ( memcmp( p, prev_p, len ) == 0 )
  800. {
  801. num_repeated++;
  802. if ( max_repeated < num_repeated ) {
  803. max_repeated = num_repeated;
  804. }
  805. } else {
  806. num_repeated = 0;
  807. }
  808. } else {
  809. num_repeated = 0;
  810. }
  811. }
  812. p = ldap_utf8next( p );
  813. }
  814. /* tally up the number of character categories */
  815. if ( num_digits > 0 )
  816. ++num_categories;
  817. if ( num_uppers > 0 )
  818. ++num_categories;
  819. if ( num_lowers > 0 )
  820. ++num_categories;
  821. if ( num_specials > 0 )
  822. ++num_categories;
  823. if ( num_8bit > 0 )
  824. ++num_categories;
  825. /* check for character based syntax limits */
  826. if ( pwpolicy->pw_mindigits > num_digits ) {
  827. syntax_violation = 1;
  828. PR_snprintf ( errormsg, BUFSIZ,
  829. "invalid password syntax - password must contain at least %d digit characters",
  830. pwpolicy->pw_mindigits );
  831. } else if ( pwpolicy->pw_minalphas > num_alphas ) {
  832. syntax_violation = 1;
  833. PR_snprintf ( errormsg, BUFSIZ,
  834. "invalid password syntax - password must contain at least %d alphabetic characters",
  835. pwpolicy->pw_minalphas );
  836. } else if ( pwpolicy->pw_minuppers > num_uppers ) {
  837. syntax_violation = 1;
  838. PR_snprintf ( errormsg, BUFSIZ,
  839. "invalid password syntax - password must contain at least %d uppercase characters",
  840. pwpolicy->pw_minuppers );
  841. } else if ( pwpolicy->pw_minlowers > num_lowers ) {
  842. syntax_violation = 1;
  843. PR_snprintf ( errormsg, BUFSIZ,
  844. "invalid password syntax - password must contain at least %d lowercase characters",
  845. pwpolicy->pw_minlowers );
  846. } else if ( pwpolicy->pw_minspecials > num_specials ) {
  847. syntax_violation = 1;
  848. PR_snprintf ( errormsg, BUFSIZ,
  849. "invalid password syntax - password must contain at least %d special characters",
  850. pwpolicy->pw_minspecials );
  851. } else if ( pwpolicy->pw_min8bit > num_8bit ) {
  852. syntax_violation = 1;
  853. PR_snprintf ( errormsg, BUFSIZ,
  854. "invalid password syntax - password must contain at least %d 8-bit characters",
  855. pwpolicy->pw_min8bit );
  856. } else if ( (pwpolicy->pw_maxrepeats != 0) && (pwpolicy->pw_maxrepeats < (max_repeated + 1)) ) {
  857. syntax_violation = 1;
  858. PR_snprintf ( errormsg, BUFSIZ,
  859. "invalid password syntax - a character cannot be repeated more than %d times",
  860. (pwpolicy->pw_maxrepeats + 1) );
  861. } else if ( pwpolicy->pw_mincategories > num_categories ) {
  862. syntax_violation = 1;
  863. PR_snprintf ( errormsg, BUFSIZ,
  864. "invalid password syntax - password must contain at least %d character "
  865. "categories (valid categories are digit, uppercase, lowercase, special, and 8-bit characters)",
  866. pwpolicy->pw_mincategories );
  867. }
  868. /* If the password failed syntax checking, send the result and return */
  869. if (syntax_violation) {
  870. if ( pwresponse_req == 1 ) {
  871. slapi_pwpolicy_make_response_control ( pb, -1, -1,
  872. LDAP_PWPOLICY_INVALIDPWDSYNTAX );
  873. }
  874. pw_send_ldap_result ( pb, LDAP_CONSTRAINT_VIOLATION, NULL, errormsg, 0, NULL );
  875. return ( 1 );
  876. }
  877. }
  878. }
  879. /* get the entry and check for the password history if this is called by a modify operation */
  880. if ( mod_op ) {
  881. /* retrieve the entry */
  882. e = get_entry ( pb, dn );
  883. if ( e == NULL ) {
  884. return ( -1 );
  885. }
  886. /* check for password history */
  887. if ( pwpolicy->pw_history == 1 ) {
  888. attr = attrlist_find(e->e_attrs, "passwordHistory");
  889. if (attr &&
  890. !valueset_isempty(&attr->a_present_values))
  891. {
  892. Slapi_Value **va= attr_get_present_values(attr);
  893. if ( pw_in_history( va, vals[0] ) == 0 ) {
  894. if ( pwresponse_req == 1 ) {
  895. slapi_pwpolicy_make_response_control ( pb, -1, -1,
  896. LDAP_PWPOLICY_PWDINHISTORY );
  897. }
  898. pw_send_ldap_result ( pb,
  899. LDAP_CONSTRAINT_VIOLATION, NULL,
  900. "password in history", 0, NULL );
  901. slapi_entry_free( e );
  902. return ( 1 );
  903. }
  904. }
  905. /* get current password. check it and remember it */
  906. attr = attrlist_find(e->e_attrs, "userpassword");
  907. if (attr && !valueset_isempty(&attr->a_present_values))
  908. {
  909. Slapi_Value **va= valueset_get_valuearray(&attr->a_present_values);
  910. if (slapi_is_encoded((char*)slapi_value_get_string(vals[0])))
  911. {
  912. if (slapi_attr_value_find(attr, (struct berval *)slapi_value_get_berval(vals[0])) == 0 )
  913. {
  914. pw_send_ldap_result ( pb,
  915. LDAP_CONSTRAINT_VIOLATION ,NULL,
  916. "password in history", 0, NULL);
  917. slapi_entry_free( e );
  918. return ( 1 );
  919. }
  920. } else
  921. {
  922. if ( slapi_pw_find_sv ( va, vals[0] ) == 0 )
  923. {
  924. pw_send_ldap_result ( pb,
  925. LDAP_CONSTRAINT_VIOLATION ,NULL,
  926. "password in history", 0, NULL);
  927. slapi_entry_free( e );
  928. return ( 1 );
  929. }
  930. }
  931. /* We copy the 1st value of the userpassword attribute.
  932. * This is because password policy assumes that there's only one
  933. * password in the userpassword attribute.
  934. */
  935. *old_pw = slapi_ch_strdup(slapi_value_get_string(va[0]));
  936. } else {
  937. *old_pw = NULL;
  938. }
  939. }
  940. }
  941. /* check for trivial words if syntax checking is enabled */
  942. if ( pwpolicy->pw_syntax == 1 ) {
  943. /* e is null if this is an add operation*/
  944. if ( check_trivial_words ( pb, e, vals, "uid", pwpolicy->pw_mintokenlength, smods ) == 1 ||
  945. check_trivial_words ( pb, e, vals, "cn", pwpolicy->pw_mintokenlength, smods ) == 1 ||
  946. check_trivial_words ( pb, e, vals, "sn", pwpolicy->pw_mintokenlength, smods ) == 1 ||
  947. check_trivial_words ( pb, e, vals, "givenname", pwpolicy->pw_mintokenlength, smods ) == 1 ||
  948. check_trivial_words ( pb, e, vals, "ou", pwpolicy->pw_mintokenlength, smods ) == 1 ||
  949. check_trivial_words ( pb, e, vals, "mail", pwpolicy->pw_mintokenlength, smods ) == 1)
  950. {
  951. if ( mod_op ) {
  952. slapi_entry_free( e );
  953. }
  954. return 1;
  955. }
  956. }
  957. if ( mod_op ) {
  958. /* free e only when called by modify operation */
  959. slapi_entry_free( e );
  960. }
  961. return 0; /* success */
  962. }
  963. static int
  964. update_pw_history( Slapi_PBlock *pb, const Slapi_DN *sdn, char *old_pw )
  965. {
  966. time_t t, old_t, cur_time;
  967. int i = 0, oldest = 0;
  968. int res;
  969. Slapi_Entry *e;
  970. Slapi_Attr *attr;
  971. LDAPMod attribute;
  972. char *values_replace[25]; /* 2-24 passwords in history */
  973. LDAPMod *list_of_mods[2];
  974. Slapi_PBlock mod_pb;
  975. char *history_str;
  976. char *str;
  977. passwdPolicy *pwpolicy = NULL;
  978. const char *dn = slapi_sdn_get_dn(sdn);
  979. pwpolicy = new_passwdPolicy(pb, dn);
  980. /* retrieve the entry */
  981. e = get_entry ( pb, dn );
  982. if ( e == NULL ) {
  983. return ( 1 );
  984. }
  985. history_str = (char *)slapi_ch_malloc(GENERALIZED_TIME_LENGTH + strlen(old_pw) + 1);
  986. /* get password history, and find the oldest password in history */
  987. cur_time = current_time ();
  988. old_t = cur_time;
  989. str = format_genTime ( cur_time );
  990. attr = attrlist_find(e->e_attrs, "passwordHistory");
  991. if (attr && !valueset_isempty(&attr->a_present_values))
  992. {
  993. Slapi_Value **va= valueset_get_valuearray(&attr->a_present_values);
  994. for ( i = oldest = 0 ;
  995. (va[i] != NULL) && (slapi_value_get_length(va[i]) > 0) ;
  996. i++ ) {
  997. values_replace[i] = (char*)slapi_value_get_string(va[i]);
  998. strncpy( history_str, values_replace[i], GENERALIZED_TIME_LENGTH);
  999. history_str[GENERALIZED_TIME_LENGTH] = '\0';
  1000. if (history_str[GENERALIZED_TIME_LENGTH - 1] != 'Z'){
  1001. /* The time is not a generalized Time. Probably a password history from 4.x */
  1002. history_str[GENERALIZED_TIME_LENGTH - 1] = '\0';
  1003. }
  1004. t = parse_genTime ( history_str );
  1005. if ( difftime ( t, old_t ) < 0 ) {
  1006. oldest = i;
  1007. old_t = t;
  1008. }
  1009. }
  1010. }
  1011. strcpy ( history_str, str );
  1012. strcat ( history_str, old_pw );
  1013. if ( i >= pwpolicy->pw_inhistory ) {
  1014. /* replace the oldest password in history */
  1015. values_replace[oldest] = history_str;
  1016. values_replace[pwpolicy->pw_inhistory] = NULL;
  1017. } else {
  1018. /* add old_pw at the end of password history */
  1019. values_replace[i] = history_str;
  1020. values_replace[++i]=NULL;
  1021. }
  1022. /* modify the attribute */
  1023. attribute.mod_type = "passwordHistory";
  1024. attribute.mod_op = LDAP_MOD_REPLACE;
  1025. attribute.mod_values = values_replace;
  1026. list_of_mods[0] = &attribute;
  1027. list_of_mods[1] = NULL;
  1028. pblock_init(&mod_pb);
  1029. slapi_modify_internal_set_pb_ext(&mod_pb, sdn, list_of_mods, NULL, NULL,
  1030. pw_get_componentID(), 0);
  1031. slapi_modify_internal_pb(&mod_pb);
  1032. slapi_pblock_get(&mod_pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
  1033. if (res != LDAP_SUCCESS){
  1034. LDAPDebug2Args(LDAP_DEBUG_ANY,
  1035. "WARNING: passwordPolicy modify error %d on entry '%s'\n", res, dn);
  1036. }
  1037. pblock_done(&mod_pb);
  1038. slapi_ch_free((void **) &str );
  1039. slapi_ch_free((void **) &history_str );
  1040. slapi_entry_free( e );
  1041. return 0;
  1042. }
  1043. static
  1044. int pw_in_history( Slapi_Value **history_vals, const Slapi_Value *pw_val)
  1045. {
  1046. Slapi_Value **trimmed_history = NULL;
  1047. int num_history_vals = 0;
  1048. int i;
  1049. int ret = -1;
  1050. const char *pw_str = slapi_value_get_string(pw_val);
  1051. if (slapi_is_encoded((char*)pw_str)){
  1052. /* If the password is encoded, we just do a string match with all previous passwords */
  1053. for ( i = 0; history_vals[i] != NULL; i++){
  1054. const char * h_val = slapi_value_get_string(history_vals[i]);
  1055. if ( h_val != NULL &&
  1056. slapi_value_get_length(history_vals[i]) >= 14 )
  1057. {
  1058. int pos = 14;
  1059. if (h_val[pos] == 'Z')
  1060. pos++;
  1061. if (strcmp(&(h_val[pos]), pw_str) == 0){
  1062. /* Password found */
  1063. /* Let's just return */
  1064. return (0);
  1065. }
  1066. }
  1067. }
  1068. } else { /* Password is in clear */
  1069. /* Count the number of history vals. */
  1070. for (i = 0; history_vals[i] != NULL; i++ )
  1071. {
  1072. num_history_vals++;
  1073. }
  1074. /* Allocate the array */
  1075. trimmed_history = (Slapi_Value **)slapi_ch_calloc(num_history_vals + 1, sizeof(Slapi_Value *));
  1076. /* strip the timestamps */
  1077. for ( i = 0; history_vals[i] != NULL; i++ )
  1078. {
  1079. char *h_val = (char *)slapi_value_get_string(history_vals[i]);
  1080. size_t h_len = slapi_value_get_length(history_vals[i]);
  1081. /* Allocate a value and put it in the array. */
  1082. trimmed_history[i] = (Slapi_Value *)slapi_ch_calloc(1, sizeof(Slapi_Value));
  1083. if ( h_val != NULL &&
  1084. h_len >= 14 )
  1085. {
  1086. /* LP: With the new genTime, the password history format has changed */
  1087. int pos = 14;
  1088. if (h_val[pos] == 'Z')
  1089. pos++;
  1090. trimmed_history[i]->bv.bv_val = &(h_val[pos]);
  1091. trimmed_history[i]->bv.bv_len = h_len - pos;
  1092. } else {
  1093. trimmed_history[i]->bv.bv_val = NULL;
  1094. trimmed_history[i]->bv.bv_len = 0;
  1095. }
  1096. }
  1097. /* NULL terminate the array. */
  1098. trimmed_history[i] = NULL;
  1099. /* Check if the new password is in the trimmed history list. */
  1100. ret = slapi_pw_find_sv(trimmed_history, pw_val);
  1101. /* Free the trimmed values. */
  1102. for ( i = 0; trimmed_history[i] != NULL; i++ )
  1103. {
  1104. slapi_ch_free((void **)&trimmed_history[i]);
  1105. }
  1106. /* Free the array. */
  1107. slapi_ch_free((void **)&trimmed_history);
  1108. }
  1109. return ( ret );
  1110. }
  1111. int
  1112. slapi_add_pwd_control ( Slapi_PBlock *pb, char *arg, long time) {
  1113. LDAPControl new_ctrl;
  1114. char buf[12];
  1115. LDAPDebug( LDAP_DEBUG_TRACE, "=> slapi_add_pwd_control\n", 0, 0, 0 );
  1116. sprintf( buf, "%ld", time );
  1117. new_ctrl.ldctl_oid = arg;
  1118. new_ctrl.ldctl_value.bv_val = buf;
  1119. new_ctrl.ldctl_value.bv_len = strlen( buf );
  1120. new_ctrl.ldctl_iscritical = 0; /* 0 = false. */
  1121. if ( slapi_pblock_set( pb, SLAPI_ADD_RESCONTROL, &new_ctrl ) != 0 ) {
  1122. return( -1 );
  1123. }
  1124. return( 0 );
  1125. }
  1126. void
  1127. pw_mod_allowchange_aci(int pw_prohibit_change)
  1128. {
  1129. const Slapi_DN *base;
  1130. char *values_mod[2];
  1131. LDAPMod mod;
  1132. LDAPMod *mods[2];
  1133. Slapi_Backend *be;
  1134. char *cookie = NULL;
  1135. mods[0] = &mod;
  1136. mods[1] = NULL;
  1137. mod.mod_type = "aci";
  1138. mod.mod_values = values_mod;
  1139. if (pw_prohibit_change) {
  1140. mod.mod_op = LDAP_MOD_ADD;
  1141. }
  1142. else
  1143. {
  1144. /* Allow change password by default */
  1145. /* remove the aci if it is there. it is ok to fail */
  1146. mod.mod_op = LDAP_MOD_DELETE;
  1147. }
  1148. be = slapi_get_first_backend (&cookie);
  1149. /* Foreach backend... */
  1150. while (be)
  1151. {
  1152. /* Don't add aci on a chaining backend holding remote entries */
  1153. if((!be->be_private) && (!slapi_be_is_flag_set(be,SLAPI_BE_FLAG_REMOTE_DATA)))
  1154. {
  1155. /* There's only One suffix per DB now. No need to loop */
  1156. base = slapi_be_getsuffix(be, 0);
  1157. if (base != NULL)
  1158. {
  1159. Slapi_PBlock pb;
  1160. int rc;
  1161. pblock_init (&pb);
  1162. values_mod[0] = DENY_PW_CHANGE_ACI;
  1163. values_mod[1] = NULL;
  1164. slapi_modify_internal_set_pb_ext(&pb, base, mods, NULL, NULL,
  1165. pw_get_componentID(), 0);
  1166. slapi_modify_internal_pb(&pb);
  1167. slapi_pblock_get(&pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
  1168. if (rc == LDAP_SUCCESS){
  1169. /*
  1170. ** Since we modified the acl
  1171. ** successfully, let's update the
  1172. ** in-memory acl list
  1173. */
  1174. slapi_pblock_set(&pb, SLAPI_TARGET_SDN, (void *)base);
  1175. plugin_call_acl_mods_update (&pb, LDAP_REQ_MODIFY );
  1176. }
  1177. pblock_done(&pb);
  1178. }
  1179. }
  1180. be = slapi_get_next_backend (cookie);
  1181. }
  1182. slapi_ch_free((void **) &cookie);
  1183. }
  1184. void
  1185. add_password_attrs( Slapi_PBlock *pb, Operation *op, Slapi_Entry *e )
  1186. {
  1187. struct berval bv;
  1188. struct berval *bvals[2];
  1189. Slapi_Attr **a, **next;
  1190. passwdPolicy *pwpolicy = NULL;
  1191. const char *dn = slapi_entry_get_ndn(e);
  1192. int has_allowchangetime = 0, has_expirationtime = 0;
  1193. time_t existing_exptime = 0;
  1194. LDAPDebug( LDAP_DEBUG_TRACE, "add_password_attrs\n", 0, 0, 0 );
  1195. bvals[0] = &bv;
  1196. bvals[1] = NULL;
  1197. /* If passwordexpirationtime is specified by the user, don't
  1198. try to assign the initial value */
  1199. for ( a = &e->e_attrs; *a != NULL; a = next ) {
  1200. if ( strcasecmp( (*a)->a_type,
  1201. "passwordexpirationtime" ) == 0) {
  1202. Slapi_Value *sval;
  1203. if (slapi_attr_first_value(*a, &sval) == 0) {
  1204. const struct berval *bv = slapi_value_get_berval(sval);
  1205. existing_exptime = parse_genTime(bv->bv_val);
  1206. }
  1207. has_expirationtime = 1;
  1208. } else if ( strcasecmp( (*a)->a_type,
  1209. "passwordallowchangetime" ) == 0) {
  1210. has_allowchangetime = 1;
  1211. }
  1212. next = &(*a)->a_next;
  1213. }
  1214. if ( has_allowchangetime && has_expirationtime ) {
  1215. return;
  1216. }
  1217. pwpolicy = new_passwdPolicy(pb, dn);
  1218. if ( !has_expirationtime &&
  1219. ( pwpolicy->pw_exp || pwpolicy->pw_must_change ) ) {
  1220. if ( pwpolicy->pw_must_change) {
  1221. /* must change password when first time logon */
  1222. bv.bv_val = format_genTime ( NO_TIME );
  1223. } else if ( pwpolicy->pw_exp ) {
  1224. bv.bv_val = format_genTime ( time_plus_sec ( current_time (),
  1225. pwpolicy->pw_maxage ) );
  1226. }
  1227. bv.bv_len = strlen( bv.bv_val );
  1228. slapi_entry_attr_merge( e, "passwordexpirationtime", bvals );
  1229. slapi_ch_free_string( &bv.bv_val );
  1230. }
  1231. /*
  1232. * If the password minimum age is not 0, calculate when the password
  1233. * is allowed to be changed again and store the result
  1234. * in passwordallowchangetime in the user's entry.
  1235. * If the password has expired, don't add passwordallowchangetime,
  1236. * otherwise if the user has grace logins, they can't be used to change
  1237. * the password if we set a passwordallowchangetime in the future.
  1238. */
  1239. if ( !has_allowchangetime && pwpolicy->pw_minage != 0 &&
  1240. (has_expirationtime && existing_exptime > current_time()) ) {
  1241. bv.bv_val = format_genTime ( time_plus_sec ( current_time (),
  1242. pwpolicy->pw_minage ) );
  1243. bv.bv_len = strlen( bv.bv_val );
  1244. slapi_entry_attr_merge( e, "passwordallowchangetime", bvals );
  1245. slapi_ch_free((void **) &bv.bv_val );
  1246. }
  1247. }
  1248. static int
  1249. check_trivial_words (Slapi_PBlock *pb, Slapi_Entry *e, Slapi_Value **vals, char *attrtype,
  1250. int toklen, Slapi_Mods *smods )
  1251. {
  1252. Slapi_Attr *attr = NULL;
  1253. Slapi_Mod *smodp = NULL, *smod = NULL;
  1254. Slapi_ValueSet *vs = NULL;
  1255. Slapi_Value *valp = NULL;
  1256. struct berval *bvp = NULL;
  1257. int i, pwresponse_req = 0;
  1258. slapi_pblock_get ( pb, SLAPI_PWPOLICY, &pwresponse_req );
  1259. /* Get a list of present values for attrtype in the existing entry, if there is one */
  1260. if (e != NULL )
  1261. {
  1262. if ( (attr = attrlist_find(e->e_attrs, attrtype)) &&
  1263. (!valueset_isempty(&attr->a_present_values)) )
  1264. {
  1265. /* allocate and add present values to valueset */
  1266. slapi_attr_get_valueset( attr, &vs );
  1267. }
  1268. }
  1269. /* allocate new one if not allocated above by
  1270. slapi_attr_get_valueset */
  1271. if (!vs) {
  1272. vs = slapi_valueset_new();
  1273. }
  1274. /* Get a list of new values for attrtype from the operation */
  1275. if ( smods && (smod = slapi_mod_new()) )
  1276. {
  1277. for (smodp = slapi_mods_get_first_smod(smods, smod);
  1278. smodp != NULL; smodp = slapi_mods_get_next_smod(smods, smod) )
  1279. {
  1280. /* Operation has new values for attrtype */
  1281. if ( PL_strcasecmp(attrtype, slapi_mod_get_type(smodp)) == 0 )
  1282. {
  1283. /* iterate through smodp values and add them if they don't exist */
  1284. for ( bvp = slapi_mod_get_first_value( smodp ); bvp != NULL;
  1285. bvp = slapi_mod_get_next_value( smodp ) )
  1286. {
  1287. /* Add new value to valueset */
  1288. valp = slapi_value_new_berval( bvp );
  1289. slapi_valueset_add_value_ext( vs, valp, SLAPI_VALUE_FLAG_PASSIN );
  1290. valp = NULL;
  1291. }
  1292. }
  1293. }
  1294. /* Free smod */
  1295. slapi_mod_free(&smod);
  1296. smod = NULL;
  1297. smodp = NULL;
  1298. }
  1299. /* If valueset isn't empty, we need to check if the password contains the values */
  1300. if ( slapi_valueset_count(vs) != 0 )
  1301. {
  1302. for ( i = slapi_valueset_first_value( vs, &valp);
  1303. (i != -1) && (valp != NULL);
  1304. i = slapi_valueset_next_value( vs, i, &valp) )
  1305. {
  1306. /* If the value is smaller than the max token length,
  1307. * we don't need to check the password */
  1308. if ( ldap_utf8characters(slapi_value_get_string( valp )) < toklen )
  1309. continue;
  1310. /* See if the password contains the value */
  1311. if ( PL_strcasestr( slapi_value_get_string( vals[0] ),
  1312. slapi_value_get_string( valp ) ) )
  1313. {
  1314. if ( pwresponse_req == 1 )
  1315. {
  1316. slapi_pwpolicy_make_response_control ( pb, -1, -1,
  1317. LDAP_PWPOLICY_INVALIDPWDSYNTAX );
  1318. }
  1319. pw_send_ldap_result ( pb,
  1320. LDAP_CONSTRAINT_VIOLATION, NULL,
  1321. "invalid password syntax - password based off of user entry", 0, NULL );
  1322. /* Free valueset */
  1323. slapi_valueset_free( vs );
  1324. return ( 1 );
  1325. }
  1326. }
  1327. }
  1328. /* Free valueset */
  1329. slapi_valueset_free( vs );
  1330. return ( 0 );
  1331. }
  1332. void
  1333. pw_add_allowchange_aci(Slapi_Entry *e, int pw_prohibit_change) {
  1334. char *aci_pw = NULL;
  1335. const char *aciattr = "aci";
  1336. aci_pw = slapi_ch_strdup(DENY_PW_CHANGE_ACI);
  1337. if (pw_prohibit_change) {
  1338. /* Add ACI */
  1339. slapi_entry_add_string(e, aciattr, aci_pw);
  1340. } else {
  1341. /* Remove ACI */
  1342. slapi_entry_delete_string(e, aciattr, aci_pw);
  1343. }
  1344. slapi_ch_free((void **) &aci_pw);
  1345. }
  1346. int
  1347. pw_is_pwp_admin(Slapi_PBlock *pb, passwdPolicy *pwp){
  1348. Slapi_DN *bind_sdn = NULL;
  1349. int i;
  1350. /* first check if it's root */
  1351. if(pb->pb_requestor_isroot){
  1352. return 1;
  1353. }
  1354. /* now check if it's a Password Policy Administrator */
  1355. slapi_pblock_get(pb, SLAPI_REQUESTOR_SDN, &bind_sdn);
  1356. if(bind_sdn == NULL){
  1357. return 0;
  1358. }
  1359. for(i = 0; pwp->pw_admin_user && pwp->pw_admin_user[i]; i++){
  1360. if(slapi_sdn_compare(bind_sdn, pwp->pw_admin_user[i]) == 0){
  1361. return 1;
  1362. }
  1363. }
  1364. return 0;
  1365. }
  1366. static void
  1367. pw_get_admin_users(passwdPolicy *pwp)
  1368. {
  1369. Slapi_PBlock *pb = NULL;
  1370. const Slapi_DN *sdn = pwp->pw_admin;
  1371. char **uniquemember_vals = NULL;
  1372. char **member_vals = NULL;
  1373. const char *binddn = slapi_sdn_get_dn(sdn);
  1374. int uniquemember_count = 0;
  1375. int member_count = 0;
  1376. int nentries = 0;
  1377. int count = 0;
  1378. int res;
  1379. int i;
  1380. if(binddn == NULL){
  1381. return;
  1382. }
  1383. /*
  1384. * Check if the DN exists and has "group" objectclasses
  1385. */
  1386. pb = slapi_pblock_new();
  1387. slapi_search_internal_set_pb(pb, binddn, LDAP_SCOPE_BASE,
  1388. "(|(objectclass=groupofuniquenames)(objectclass=groupofnames))",
  1389. NULL, 0, NULL, NULL, (void *) plugin_get_default_component_id(), 0);
  1390. slapi_search_internal_pb(pb);
  1391. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
  1392. if (res != LDAP_SUCCESS) {
  1393. slapi_free_search_results_internal(pb);
  1394. slapi_pblock_destroy(pb);
  1395. LDAPDebug(LDAP_DEBUG_ANY, "pw_get_admin_users: search failed for %s: error %d - "
  1396. "Password Policy Administrators can not be set\n",
  1397. slapi_sdn_get_dn(sdn), res, 0);
  1398. return;
  1399. }
  1400. /*
  1401. * Ok, we know we have a valid DN, and nentries will tell us if its a group or a user
  1402. */
  1403. slapi_pblock_get(pb, SLAPI_NENTRIES, &nentries);
  1404. if ( nentries > 0 ){
  1405. /*
  1406. * It's a group DN, gather all the members
  1407. */
  1408. Slapi_Entry **entries = NULL;
  1409. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
  1410. uniquemember_vals = slapi_entry_attr_get_charray_ext(entries[0], "uniquemember", &uniquemember_count);
  1411. member_vals = slapi_entry_attr_get_charray_ext(entries[0], "member", &member_count);
  1412. pwp->pw_admin_user = (Slapi_DN **)slapi_ch_calloc((uniquemember_count + member_count + 1),
  1413. sizeof(Slapi_DN *));
  1414. if(uniquemember_count > 0){
  1415. for(i = 0; i < uniquemember_count; i++){
  1416. pwp->pw_admin_user[count++] = slapi_sdn_new_dn_passin(uniquemember_vals[i]);
  1417. }
  1418. }
  1419. if(member_count > 0){
  1420. for(i = 0; i < member_count; i++){
  1421. pwp->pw_admin_user[count++] = slapi_sdn_new_dn_passin(member_vals[i]);
  1422. }
  1423. }
  1424. slapi_ch_free((void**)&uniquemember_vals);
  1425. slapi_ch_free((void**)&member_vals);
  1426. } else {
  1427. /* It's a single user */
  1428. pwp->pw_admin_user = (Slapi_DN **)slapi_ch_calloc(2, sizeof(Slapi_DN *));
  1429. pwp->pw_admin_user[0] = slapi_sdn_dup(sdn);
  1430. }
  1431. slapi_free_search_results_internal(pb);
  1432. slapi_pblock_destroy(pb);
  1433. }
  1434. /* This function creates a passwdPolicy structure, loads it from either
  1435. * slapdFrontendconfig or the entry pointed by pwdpolicysubentry and
  1436. * returns the structure.
  1437. */
  1438. passwdPolicy *
  1439. new_passwdPolicy(Slapi_PBlock *pb, const char *dn)
  1440. {
  1441. Slapi_ValueSet *values = NULL;
  1442. Slapi_Entry *e = NULL, *pw_entry = NULL;
  1443. int type_name_disposition = 0;
  1444. char *actual_type_name = NULL;
  1445. int attr_free_flags = 0;
  1446. int rc=0;
  1447. passwdPolicy *pwdpolicy = NULL;
  1448. struct pw_scheme *pwdscheme = NULL;
  1449. Slapi_Attr *attr;
  1450. char *attr_name;
  1451. Slapi_Value **sval;
  1452. slapdFrontendConfig_t *slapdFrontendConfig;
  1453. int optype = -1;
  1454. /* If we already allocated a pw policy, return it */
  1455. if(pb && pb->pwdpolicy){
  1456. return pb->pwdpolicy;
  1457. }
  1458. if (g_get_active_threadcnt() == 0){
  1459. /*
  1460. * If the server is starting up the thread count will be zero, so
  1461. * we should not proceed, because not all the backends have been
  1462. * initialized yet.
  1463. */
  1464. return NULL;
  1465. }
  1466. if (pb) {
  1467. slapi_pblock_get( pb, SLAPI_OPERATION_TYPE, &optype );
  1468. }
  1469. slapdFrontendConfig = getFrontendConfig();
  1470. pwdpolicy = (passwdPolicy *)slapi_ch_calloc(1, sizeof(passwdPolicy));
  1471. if (dn && (slapdFrontendConfig->pwpolicy_local == 1)) {
  1472. /* If we're doing an add, COS does not apply yet so we check
  1473. parents for the pwdpolicysubentry. We look only for virtual
  1474. attributes, because real ones are for single-target policy. */
  1475. /* RFE - is there a way to make this work for non-existent entries
  1476. * when we don't pass in pb? We'll need to do this if we add support
  1477. * for password policy plug-ins. */
  1478. if (optype == SLAPI_OPERATION_ADD) {
  1479. char *parentdn = slapi_ch_strdup(dn);
  1480. char *nextdn = NULL;
  1481. while ((nextdn = slapi_dn_parent( parentdn )) != NULL) {
  1482. if (((e = get_entry( pb, nextdn )) != NULL)) {
  1483. if ((slapi_vattr_values_get(e, "pwdpolicysubentry",
  1484. &values, &type_name_disposition, &actual_type_name,
  1485. SLAPI_VIRTUALATTRS_REQUEST_POINTERS |
  1486. SLAPI_VIRTUALATTRS_ONLY,
  1487. &attr_free_flags)) == 0) {
  1488. /* pwdpolicysubentry found! */
  1489. break;
  1490. } else {
  1491. /* Parent didn't have it, check grandparent... */
  1492. slapi_ch_free_string( &parentdn );
  1493. parentdn = nextdn;
  1494. slapi_entry_free( e );
  1495. e = NULL;
  1496. }
  1497. } else {
  1498. /* Reached the top without finding a pwdpolicysubentry. */
  1499. break;
  1500. }
  1501. }
  1502. slapi_ch_free_string( &parentdn );
  1503. slapi_ch_free_string( &nextdn );
  1504. /* If we're not doing an add, we look for the pwdpolicysubentry
  1505. attribute in the target entry itself. */
  1506. } else {
  1507. if ( (e = get_entry( pb, dn )) != NULL ) {
  1508. rc = slapi_vattr_values_get(e, "pwdpolicysubentry", &values,
  1509. &type_name_disposition, &actual_type_name,
  1510. SLAPI_VIRTUALATTRS_REQUEST_POINTERS, &attr_free_flags);
  1511. if (rc) {
  1512. values = NULL;
  1513. }
  1514. }
  1515. }
  1516. if (values != NULL) {
  1517. Slapi_Value *v = NULL;
  1518. const struct berval *bvp = NULL;
  1519. if ( ((rc = slapi_valueset_first_value( values, &v )) != -1) &&
  1520. ( bvp = slapi_value_get_berval( v )) != NULL ) {
  1521. if ( bvp != NULL ) {
  1522. /* we got the pwdpolicysubentry value */
  1523. pw_entry = get_entry ( pb, bvp->bv_val);
  1524. }
  1525. }
  1526. slapi_vattr_values_free(&values, &actual_type_name, attr_free_flags);
  1527. slapi_entry_free( e );
  1528. if ( pw_entry == NULL ) {
  1529. LDAPDebug1Arg(LDAP_DEBUG_ANY,
  1530. "loading global password policy for %s"
  1531. "--local policy entry not found\n", dn);
  1532. goto done;
  1533. }
  1534. /* set the default passwordLegacyPolicy setting */
  1535. pwdpolicy->pw_is_legacy = 1;
  1536. /* set passwordTrackUpdateTime */
  1537. pwdpolicy->pw_track_update_time = slapdFrontendConfig->pw_policy.pw_track_update_time;
  1538. for (slapi_entry_first_attr(pw_entry, &attr); attr;
  1539. slapi_entry_next_attr(pw_entry, attr, &attr))
  1540. {
  1541. slapi_attr_get_type(attr, &attr_name);
  1542. if (!strcasecmp(attr_name, "passwordminage")) {
  1543. if ((sval = attr_get_present_values(attr))) {
  1544. pwdpolicy->pw_minage = slapi_value_get_timelong(*sval);
  1545. if (-1 == pwdpolicy->pw_minage) {
  1546. LDAPDebug2Args(LDAP_DEBUG_ANY,
  1547. "Password Policy Entry%s: Invalid passwordMinAge: %s\n",
  1548. slapi_entry_get_dn_const(pw_entry),
  1549. slapi_value_get_string(*sval));
  1550. }
  1551. }
  1552. }
  1553. else
  1554. if (!strcasecmp(attr_name, "passwordmaxage")) {
  1555. if ((sval = attr_get_present_values(attr))) {
  1556. pwdpolicy->pw_maxage = slapi_value_get_timelong(*sval);
  1557. if (-1 == pwdpolicy->pw_maxage) {
  1558. LDAPDebug2Args(LDAP_DEBUG_ANY,
  1559. "Password Policy Entry%s: Invalid passwordMaxAge: %s\n",
  1560. slapi_entry_get_dn_const(pw_entry),
  1561. slapi_value_get_string(*sval));
  1562. }
  1563. }
  1564. }
  1565. else
  1566. if (!strcasecmp(attr_name, "passwordwarning")) {
  1567. if ((sval = attr_get_present_values(attr))) {
  1568. pwdpolicy->pw_warning = slapi_value_get_timelong(*sval);
  1569. if (-1 == pwdpolicy->pw_warning) {
  1570. LDAPDebug2Args(LDAP_DEBUG_ANY,
  1571. "Password Policy Entry%s: Invalid passwordWarning: %s\n",
  1572. slapi_entry_get_dn_const(pw_entry),
  1573. slapi_value_get_string(*sval));
  1574. }
  1575. }
  1576. }
  1577. else
  1578. if (!strcasecmp(attr_name, "passwordhistory")) {
  1579. if ((sval = attr_get_present_values(attr))) {
  1580. pwdpolicy->pw_history =
  1581. pw_boolean_str2value(slapi_value_get_string(*sval));
  1582. }
  1583. }
  1584. else
  1585. if (!strcasecmp(attr_name, "passwordinhistory")) {
  1586. if ((sval = attr_get_present_values(attr))) {
  1587. pwdpolicy->pw_inhistory = slapi_value_get_int(*sval);
  1588. }
  1589. }
  1590. else
  1591. if (!strcasecmp(attr_name, "passwordlockout")) {
  1592. if ((sval = attr_get_present_values(attr))) {
  1593. pwdpolicy->pw_lockout =
  1594. pw_boolean_str2value(slapi_value_get_string(*sval));
  1595. }
  1596. }
  1597. else
  1598. if (!strcasecmp(attr_name, "passwordmaxfailure")) {
  1599. if ((sval = attr_get_present_values(attr))) {
  1600. pwdpolicy->pw_maxfailure = slapi_value_get_int(*sval);
  1601. }
  1602. }
  1603. else
  1604. if (!strcasecmp(attr_name, "passwordunlock")) {
  1605. if ((sval = attr_get_present_values(attr))) {
  1606. pwdpolicy->pw_unlock =
  1607. pw_boolean_str2value(slapi_value_get_string(*sval));
  1608. }
  1609. }
  1610. else
  1611. if (!strcasecmp(attr_name, "passwordlockoutduration")) {
  1612. if ((sval = attr_get_present_values(attr))) {
  1613. pwdpolicy->pw_lockduration = slapi_value_get_timelong(*sval);
  1614. }
  1615. }
  1616. else
  1617. if (!strcasecmp(attr_name, "passwordresetfailurecount")) {
  1618. if ((sval = attr_get_present_values(attr))) {
  1619. pwdpolicy->pw_resetfailurecount = slapi_value_get_long(*sval);
  1620. }
  1621. }
  1622. else
  1623. if (!strcasecmp(attr_name, "passwordchange")) {
  1624. if ((sval = attr_get_present_values(attr))) {
  1625. pwdpolicy->pw_change =
  1626. pw_boolean_str2value(slapi_value_get_string(*sval));
  1627. }
  1628. }
  1629. else
  1630. if (!strcasecmp(attr_name, "passwordmustchange")) {
  1631. if ((sval = attr_get_present_values(attr))) {
  1632. pwdpolicy->pw_must_change =
  1633. pw_boolean_str2value(slapi_value_get_string(*sval));
  1634. }
  1635. }
  1636. else
  1637. if (!strcasecmp(attr_name, "passwordchecksyntax")) {
  1638. if ((sval = attr_get_present_values(attr))) {
  1639. pwdpolicy->pw_syntax =
  1640. pw_boolean_str2value(slapi_value_get_string(*sval));
  1641. }
  1642. }
  1643. else
  1644. if (!strcasecmp(attr_name, "passwordminlength")) {
  1645. if ((sval = attr_get_present_values(attr))) {
  1646. pwdpolicy->pw_minlength = slapi_value_get_int(*sval);
  1647. }
  1648. }
  1649. else
  1650. if (!strcasecmp(attr_name, "passwordmindigits")) {
  1651. if ((sval = attr_get_present_values(attr))) {
  1652. pwdpolicy->pw_mindigits = slapi_value_get_int(*sval);
  1653. }
  1654. }
  1655. else
  1656. if (!strcasecmp(attr_name, "passwordminalphas")) {
  1657. if ((sval = attr_get_present_values(attr))) {
  1658. pwdpolicy->pw_minalphas = slapi_value_get_int(*sval);
  1659. }
  1660. }
  1661. else
  1662. if (!strcasecmp(attr_name, "passwordminuppers")) {
  1663. if ((sval = attr_get_present_values(attr))) {
  1664. pwdpolicy->pw_minuppers = slapi_value_get_int(*sval);
  1665. }
  1666. }
  1667. else
  1668. if (!strcasecmp(attr_name, "passwordminlowers")) {
  1669. if ((sval = attr_get_present_values(attr))) {
  1670. pwdpolicy->pw_minlowers = slapi_value_get_int(*sval);
  1671. }
  1672. }
  1673. else
  1674. if (!strcasecmp(attr_name, "passwordminspecials")) {
  1675. if ((sval = attr_get_present_values(attr))) {
  1676. pwdpolicy->pw_minspecials = slapi_value_get_int(*sval);
  1677. }
  1678. }
  1679. else
  1680. if (!strcasecmp(attr_name, "passwordmin8bit")) {
  1681. if ((sval = attr_get_present_values(attr))) {
  1682. pwdpolicy->pw_min8bit = slapi_value_get_int(*sval);
  1683. }
  1684. }
  1685. else
  1686. if (!strcasecmp(attr_name, "passwordmaxrepeats")) {
  1687. if ((sval = attr_get_present_values(attr))) {
  1688. pwdpolicy->pw_maxrepeats = slapi_value_get_int(*sval);
  1689. }
  1690. }
  1691. else
  1692. if (!strcasecmp(attr_name, "passwordmincategories")) {
  1693. if ((sval = attr_get_present_values(attr))) {
  1694. pwdpolicy->pw_mincategories = slapi_value_get_int(*sval);
  1695. }
  1696. }
  1697. else
  1698. if (!strcasecmp(attr_name, "passwordmintokenlength")) {
  1699. if ((sval = attr_get_present_values(attr))) {
  1700. pwdpolicy->pw_mintokenlength = slapi_value_get_int(*sval);
  1701. }
  1702. }
  1703. else
  1704. if (!strcasecmp(attr_name, "passwordexp")) {
  1705. if ((sval = attr_get_present_values(attr))) {
  1706. pwdpolicy->pw_exp =
  1707. pw_boolean_str2value(slapi_value_get_string(*sval));
  1708. }
  1709. }
  1710. else
  1711. if (!strcasecmp(attr_name, "passwordgracelimit")) {
  1712. if ((sval = attr_get_present_values(attr))) {
  1713. pwdpolicy->pw_gracelimit = slapi_value_get_int(*sval);
  1714. }
  1715. }
  1716. else
  1717. if (!strcasecmp(attr_name, "passwordstoragescheme")) {
  1718. if ((sval = attr_get_present_values(attr))) {
  1719. pwdpolicy->pw_storagescheme =
  1720. pw_name2scheme((char*)slapi_value_get_string(*sval));
  1721. }
  1722. }
  1723. else
  1724. if (!strcasecmp(attr_name, "passwordLegacyPolicy")) {
  1725. if ((sval = attr_get_present_values(attr))) {
  1726. pwdpolicy->pw_is_legacy =
  1727. pw_boolean_str2value(slapi_value_get_string(*sval));
  1728. }
  1729. }
  1730. else
  1731. if (!strcasecmp(attr_name, "passwordTrackUpdateTime")) {
  1732. if ((sval = attr_get_present_values(attr))) {
  1733. pwdpolicy->pw_track_update_time =
  1734. pw_boolean_str2value(slapi_value_get_string(*sval));
  1735. }
  1736. }
  1737. else
  1738. if (!strcasecmp(attr_name, "passwordAdminDN")) {
  1739. if ((sval = attr_get_present_values(attr))) {
  1740. pwdpolicy->pw_admin = slapi_sdn_new_dn_byval(slapi_value_get_string(*sval));
  1741. pw_get_admin_users(pwdpolicy);
  1742. }
  1743. }
  1744. } /* end of for() loop */
  1745. if (pw_entry) {
  1746. slapi_entry_free(pw_entry);
  1747. }
  1748. if(pb){
  1749. pb->pwdpolicy = pwdpolicy;
  1750. }
  1751. return pwdpolicy;
  1752. } else if ( e ) {
  1753. slapi_entry_free( e );
  1754. }
  1755. }
  1756. done:
  1757. /*
  1758. * If we are here, that means we need to load the passwdPolicy
  1759. * structure from slapdFrontendconfig
  1760. */
  1761. *pwdpolicy = slapdFrontendConfig->pw_policy;
  1762. pwdscheme = (struct pw_scheme *)slapi_ch_calloc(1, sizeof(struct pw_scheme));
  1763. *pwdscheme = *slapdFrontendConfig->pw_storagescheme;
  1764. pwdscheme->pws_name = strdup( slapdFrontendConfig->pw_storagescheme->pws_name );
  1765. pwdpolicy->pw_storagescheme = pwdscheme;
  1766. pwdpolicy->pw_admin = slapi_sdn_dup(slapdFrontendConfig->pw_policy.pw_admin);
  1767. pw_get_admin_users(pwdpolicy);
  1768. if(pb){
  1769. pb->pwdpolicy = pwdpolicy;
  1770. }
  1771. return pwdpolicy;
  1772. } /* End of new_passwdPolicy() */
  1773. void
  1774. delete_passwdPolicy( passwdPolicy **pwpolicy)
  1775. {
  1776. if (pwpolicy && *pwpolicy) {
  1777. free_pw_scheme( (*(*pwpolicy)).pw_storagescheme );
  1778. slapi_sdn_free(&(*(*pwpolicy)).pw_admin);
  1779. if((*(*pwpolicy)).pw_admin_user){
  1780. int i = 0;
  1781. while((*(*pwpolicy)).pw_admin_user[i]){
  1782. slapi_sdn_free(&(*(*pwpolicy)).pw_admin_user[i]);
  1783. i++;
  1784. }
  1785. slapi_ch_free((void **)&(*(*pwpolicy)).pw_admin_user);
  1786. }
  1787. slapi_ch_free((void **)pwpolicy);
  1788. }
  1789. }
  1790. /*
  1791. * Encode the PWPOLICY RESPONSE control.
  1792. *
  1793. * Create a password policy response control,
  1794. * and add it to the PBlock to be returned to the client.
  1795. *
  1796. * Returns:
  1797. * success ( 0 )
  1798. * operationsError (1),
  1799. */
  1800. int
  1801. slapi_pwpolicy_make_response_control (Slapi_PBlock *pb, int seconds, int logins, ber_int_t error)
  1802. {
  1803. BerElement *ber= NULL;
  1804. struct berval *bvp = NULL;
  1805. int rc = -1;
  1806. /*
  1807. PasswordPolicyResponseValue ::= SEQUENCE {
  1808. warning [0] CHOICE OPTIONAL {
  1809. timeBeforeExpiration [0] INTEGER (0 .. maxInt),
  1810. graceLoginsRemaining [1] INTEGER (0 .. maxInt) }
  1811. error [1] ENUMERATED OPTIONAL {
  1812. passwordExpired (0),
  1813. accountLocked (1),
  1814. changeAfterReset (2),
  1815. passwordModNotAllowed (3),
  1816. mustSupplyOldPassword (4),
  1817. invalidPasswordSyntax (5),
  1818. passwordTooShort (6),
  1819. passwordTooYoung (7),
  1820. passwordInHistory (8) } }
  1821. */
  1822. LDAPDebug( LDAP_DEBUG_TRACE, "=> slapi_pwpolicy_make_response_control", 0, 0, 0 );
  1823. if ( ( ber = ber_alloc()) == NULL )
  1824. {
  1825. return rc;
  1826. }
  1827. rc = ber_printf( ber, "{" );
  1828. if ( seconds >= 0 || logins >= 0 ) {
  1829. if ( seconds >= 0 ) {
  1830. rc = ber_printf( ber, "t{ti}", LDAP_TAG_PWP_WARNING,
  1831. LDAP_TAG_PWP_SECSLEFT,
  1832. seconds );
  1833. }
  1834. else {
  1835. rc = ber_printf( ber, "t{ti}", LDAP_TAG_PWP_WARNING,
  1836. LDAP_TAG_PWP_GRCLOGINS,
  1837. logins );
  1838. }
  1839. }
  1840. if ( error >= 0 ) {
  1841. rc = ber_printf( ber, "te", LDAP_TAG_PWP_ERROR, error );
  1842. }
  1843. rc = ber_printf( ber, "}" );
  1844. if ( rc != -1 )
  1845. {
  1846. rc = ber_flatten( ber, &bvp );
  1847. }
  1848. ber_free( ber, 1 );
  1849. if ( rc != -1 )
  1850. {
  1851. LDAPControl new_ctrl = {0};
  1852. new_ctrl.ldctl_oid = LDAP_X_CONTROL_PWPOLICY_RESPONSE;
  1853. new_ctrl.ldctl_value = *bvp;
  1854. new_ctrl.ldctl_iscritical = 0;
  1855. rc= slapi_pblock_set( pb, SLAPI_ADD_RESCONTROL, &new_ctrl );
  1856. ber_bvfree(bvp);
  1857. }
  1858. LDAPDebug( LDAP_DEBUG_TRACE, "<= slapi_pwpolicy_make_response_control", 0, 0, 0 );
  1859. return (rc==-1?LDAP_OPERATIONS_ERROR:LDAP_SUCCESS);
  1860. }
  1861. static int
  1862. pw_boolean_str2value (const char *str)
  1863. {
  1864. if ( !strcasecmp(str, "true") ||
  1865. !strcasecmp(str, "on") ||
  1866. !strcasecmp(str, "1") ) {
  1867. return ( LDAP_ON );
  1868. }
  1869. if ( !strcasecmp(str, "false") ||
  1870. !strcasecmp(str, "off") ||
  1871. !strcasecmp(str, "0") ) {
  1872. return ( LDAP_OFF );
  1873. }
  1874. return (-1);
  1875. }
  1876. int
  1877. check_pw_duration_value( const char *attr_name, char *value,
  1878. long minval, long maxval, char *errorbuf )
  1879. {
  1880. int retVal = LDAP_SUCCESS;
  1881. long age;
  1882. age = parse_duration(value);
  1883. if (-1 == age) {
  1884. PR_snprintf ( errorbuf, BUFSIZ,
  1885. "password minimum age \"%s\" is invalid. ", value );
  1886. retVal = LDAP_CONSTRAINT_VIOLATION;
  1887. } else if (0 == strcasecmp(CONFIG_PW_LOCKDURATION_ATTRIBUTE, attr_name)) {
  1888. if ( (age <= 0) ||
  1889. (age > (MAX_ALLOWED_TIME_IN_SECS - current_time())) ||
  1890. ((-1 != minval) && (age < minval)) ||
  1891. ((-1 != maxval) && (age > maxval))) {
  1892. PR_snprintf ( errorbuf, BUFSIZ, "%s: \"%s\" seconds is invalid. ",
  1893. attr_name, value );
  1894. retVal = LDAP_CONSTRAINT_VIOLATION;
  1895. }
  1896. } else {
  1897. if ( (age < 0) ||
  1898. (age > (MAX_ALLOWED_TIME_IN_SECS - current_time())) ||
  1899. ((-1 != minval) && (age < minval)) ||
  1900. ((-1 != maxval) && (age > maxval))) {
  1901. PR_snprintf ( errorbuf, BUFSIZ, "%s: \"%s\" seconds is invalid. ",
  1902. attr_name, value );
  1903. retVal = LDAP_CONSTRAINT_VIOLATION;
  1904. }
  1905. }
  1906. return retVal;
  1907. }
  1908. int
  1909. check_pw_resetfailurecount_value( const char *attr_name, char *value, long minval, long maxval, char *errorbuf )
  1910. {
  1911. int retVal = LDAP_SUCCESS;
  1912. long duration = 0; /* in minutes */
  1913. /* in seconds */
  1914. duration = strtol (value, NULL, 0);
  1915. if ( duration < 0 || duration > (MAX_ALLOWED_TIME_IN_SECS - current_time()) ) {
  1916. PR_snprintf ( errorbuf, BUFSIZ,
  1917. "password reset count duration \"%s\" seconds is invalid. ",
  1918. value );
  1919. retVal = LDAP_CONSTRAINT_VIOLATION;
  1920. }
  1921. return retVal;
  1922. }
  1923. int
  1924. check_pw_storagescheme_value( const char *attr_name, char *value, long minval, long maxval, char *errorbuf )
  1925. {
  1926. int retVal = LDAP_SUCCESS;
  1927. struct pw_scheme *new_scheme = NULL;
  1928. char * scheme_list = NULL;
  1929. scheme_list = plugin_get_pwd_storage_scheme_list(PLUGIN_LIST_PWD_STORAGE_SCHEME);
  1930. new_scheme = pw_name2scheme(value);
  1931. if ( new_scheme == NULL) {
  1932. if ( scheme_list != NULL ) {
  1933. PR_snprintf ( errorbuf, BUFSIZ,
  1934. "%s: invalid scheme - %s. Valid schemes are: %s",
  1935. CONFIG_PW_STORAGESCHEME_ATTRIBUTE, value, scheme_list );
  1936. } else {
  1937. PR_snprintf ( errorbuf, BUFSIZ,
  1938. "%s: invalid scheme - %s (no pwdstorage scheme"
  1939. " plugin loaded)",
  1940. CONFIG_PW_STORAGESCHEME_ATTRIBUTE, value);
  1941. }
  1942. retVal = LDAP_CONSTRAINT_VIOLATION;
  1943. }
  1944. else if ( new_scheme->pws_enc == NULL )
  1945. {
  1946. /* For example: the NS-MTA-MD5 password scheme is for comparision only
  1947. and for backward compatibility with an Old Messaging Server that was
  1948. setting passwords in the directory already encrypted. The scheme cannot
  1949. and won't encrypt passwords if they are in clear. We don't take it
  1950. */
  1951. if ( scheme_list != NULL ) {
  1952. PR_snprintf ( errorbuf, BUFSIZ,
  1953. "%s: invalid encoding scheme - %s\nValid values are: %s\n",
  1954. CONFIG_PW_STORAGESCHEME_ATTRIBUTE, value, scheme_list );
  1955. }
  1956. retVal = LDAP_CONSTRAINT_VIOLATION;
  1957. }
  1958. free_pw_scheme(new_scheme);
  1959. slapi_ch_free_string(&scheme_list);
  1960. return retVal;
  1961. }
  1962. /* check_account_lock is called before bind opeation; this could be a pre-op. */
  1963. int
  1964. slapi_check_account_lock ( Slapi_PBlock *pb, Slapi_Entry * bind_target_entry, int pwresponse_req, int check_password_policy, int send_result) {
  1965. time_t unlock_time;
  1966. time_t cur_time;
  1967. char *cur_time_str = NULL;
  1968. char *accountUnlockTime;
  1969. passwdPolicy *pwpolicy = NULL;
  1970. char *dn = NULL;
  1971. /* kexcoff: account inactivation */
  1972. int rc = 0;
  1973. Slapi_ValueSet *values = NULL;
  1974. int type_name_disposition = 0;
  1975. char *actual_type_name = NULL;
  1976. int attr_free_flags = 0;
  1977. /* kexcoff - end */
  1978. if ( bind_target_entry == NULL )
  1979. return -1;
  1980. if(check_password_policy)
  1981. {
  1982. dn = slapi_entry_get_ndn(bind_target_entry);
  1983. pwpolicy = new_passwdPolicy(pb, dn);
  1984. }
  1985. /* kexcoff: account inactivation */
  1986. /* check if the entry is locked by nsAccountLock attribute - account inactivation feature */
  1987. rc = slapi_vattr_values_get(bind_target_entry, "nsAccountLock",
  1988. &values,
  1989. &type_name_disposition, &actual_type_name,
  1990. SLAPI_VIRTUALATTRS_REQUEST_POINTERS,
  1991. &attr_free_flags);
  1992. if ( rc == 0 && NULL != values )
  1993. {
  1994. Slapi_Value *v = NULL;
  1995. const struct berval *bvp = NULL;
  1996. if ( (slapi_valueset_first_value( values, &v ) != -1) &&
  1997. ( bvp = slapi_value_get_berval( v )) != NULL )
  1998. {
  1999. if ( (bvp != NULL) && (strcasecmp(bvp->bv_val, "true") == 0) )
  2000. {
  2001. /* account inactivated */
  2002. if (check_password_policy && pwresponse_req) {
  2003. slapi_pwpolicy_make_response_control ( pb, -1, -1,
  2004. LDAP_PWPOLICY_ACCTLOCKED );
  2005. }
  2006. if (send_result)
  2007. send_ldap_result ( pb, LDAP_UNWILLING_TO_PERFORM, NULL,
  2008. "Account inactivated. Contact system administrator.",
  2009. 0, NULL );
  2010. slapi_vattr_values_free(&values, &actual_type_name, attr_free_flags);
  2011. goto locked;
  2012. }
  2013. } /* else, account "activated", keep on the process */
  2014. }
  2015. if ( values != NULL )
  2016. slapi_vattr_values_free(&values, &actual_type_name, attr_free_flags);
  2017. /* kexcoff - end */
  2018. /*
  2019. * Check if the password policy has to be checked or not
  2020. */
  2021. if ( !check_password_policy || pwpolicy->pw_lockout == 0 ) {
  2022. goto notlocked;
  2023. }
  2024. /*
  2025. * Check the attribute of the password policy
  2026. */
  2027. /* check if account is locked out. If so, send result and return 1 */
  2028. {
  2029. unsigned int maxfailure= pwpolicy->pw_maxfailure;
  2030. /* It's locked if passwordRetryCount >= maxfailure */
  2031. if ( slapi_entry_attr_get_uint(bind_target_entry,"passwordRetryCount") < maxfailure )
  2032. {
  2033. /* Not locked */
  2034. goto notlocked;
  2035. }
  2036. }
  2037. /* locked but maybe it's time to unlock it */
  2038. accountUnlockTime= slapi_entry_attr_get_charptr(bind_target_entry, "accountUnlockTime");
  2039. if (accountUnlockTime != NULL)
  2040. {
  2041. unlock_time = parse_genTime(accountUnlockTime);
  2042. slapi_ch_free((void **) &accountUnlockTime );
  2043. if ( pwpolicy->pw_unlock == 0 &&
  2044. unlock_time == NO_TIME ) {
  2045. /* account is locked forever. contact admin to reset */
  2046. if (pwresponse_req) {
  2047. slapi_pwpolicy_make_response_control ( pb, -1, -1,
  2048. LDAP_PWPOLICY_ACCTLOCKED );
  2049. }
  2050. if (send_result)
  2051. send_ldap_result ( pb, LDAP_CONSTRAINT_VIOLATION, NULL,
  2052. "Exceed password retry limit. Contact system administrator to reset.",
  2053. 0, NULL );
  2054. goto locked;
  2055. }
  2056. cur_time = current_time();
  2057. cur_time_str = format_genTime( cur_time);
  2058. if ( difftime ( parse_genTime( cur_time_str ), unlock_time ) < 0 ) {
  2059. /* account is locked, cannot do anything */
  2060. if (pwresponse_req) {
  2061. slapi_pwpolicy_make_response_control ( pb, -1, -1,
  2062. LDAP_PWPOLICY_ACCTLOCKED );
  2063. }
  2064. if (send_result)
  2065. send_ldap_result ( pb, LDAP_CONSTRAINT_VIOLATION, NULL,
  2066. "Exceed password retry limit. Please try later.",
  2067. 0, NULL );
  2068. slapi_ch_free((void **) &cur_time_str );
  2069. goto locked;
  2070. }
  2071. slapi_ch_free((void **) &cur_time_str );
  2072. }
  2073. notlocked:
  2074. /* account is not locked. */
  2075. return (0);
  2076. locked:
  2077. return (1);
  2078. }
  2079. /* The idea here is that these functions could allow us to have password
  2080. * policy plugins in the future. The plugins would register callbacks for these
  2081. * slapi functions that would be used here if any pwpolicy plugin is configured to
  2082. * be used. Right now, we just use the normal server password policy code since
  2083. * we don't have a pwpolicy plugin type. */
  2084. Slapi_PWPolicy *
  2085. slapi_get_pwpolicy(Slapi_DN *dn)
  2086. {
  2087. return ((Slapi_PWPolicy *)new_passwdPolicy(NULL, slapi_sdn_get_ndn(dn)));
  2088. }
  2089. void
  2090. slapi_pwpolicy_free(Slapi_PWPolicy *pwpolicy)
  2091. {
  2092. delete_passwdPolicy((passwdPolicy **)&pwpolicy);
  2093. }
  2094. int
  2095. slapi_pwpolicy_is_expired(Slapi_PWPolicy *pwpolicy, Slapi_Entry *e, time_t *expire_time, int *remaining_grace)
  2096. {
  2097. int is_expired = 0;
  2098. if (pwpolicy && e) {
  2099. /* If password expiration is enabled in the policy,
  2100. * check if the password has expired. */
  2101. if (pwpolicy->pw_exp == 1) {
  2102. char *expiration_val = NULL;
  2103. time_t _expire_time;
  2104. double diff_t = 0;
  2105. char *cur_time_str = NULL;
  2106. time_t cur_time;
  2107. expiration_val = slapi_entry_attr_get_charptr(e, "passwordExpirationTime");
  2108. if (expiration_val) {
  2109. _expire_time = parse_genTime(expiration_val);
  2110. cur_time = current_time();
  2111. cur_time_str = format_genTime(cur_time);
  2112. if ((_expire_time != NO_TIME) && (_expire_time != NOT_FIRST_TIME) &&
  2113. ((diff_t = difftime (_expire_time, parse_genTime(cur_time_str))) <= 0)) {
  2114. is_expired = 1;
  2115. }
  2116. if (is_expired) {
  2117. if (remaining_grace) {
  2118. /* Fill in the number of remaining grace logins */
  2119. int grace_attempts = 0;
  2120. grace_attempts = slapi_entry_attr_get_int(e, "passwordGraceUserTime");
  2121. if (pwpolicy->pw_gracelimit > grace_attempts) {
  2122. *remaining_grace = pwpolicy->pw_gracelimit - grace_attempts;
  2123. } else {
  2124. *remaining_grace = 0;
  2125. }
  2126. }
  2127. } else if (expire_time) {
  2128. /* Fill in the expiration time */
  2129. if ((_expire_time != NO_TIME) && (_expire_time != NOT_FIRST_TIME)) {
  2130. *expire_time = _expire_time;
  2131. } else {
  2132. *expire_time = (time_t)0;
  2133. }
  2134. }
  2135. slapi_ch_free_string(&cur_time_str);
  2136. }
  2137. } else if (expire_time) {
  2138. /* Passwords never expire */
  2139. *expire_time = (time_t)0;
  2140. }
  2141. }
  2142. return is_expired;
  2143. }
  2144. int
  2145. slapi_pwpolicy_is_locked(Slapi_PWPolicy *pwpolicy, Slapi_Entry *e, time_t *unlock_time)
  2146. {
  2147. int is_locked = 0;
  2148. if (pwpolicy && e) {
  2149. /* Check if account is locked */
  2150. if ( pwpolicy->pw_lockout == 1) {
  2151. if (slapi_entry_attr_get_uint(e, "passwordRetryCount") >= pwpolicy->pw_maxfailure) {
  2152. is_locked = 1;
  2153. }
  2154. }
  2155. if (is_locked) {
  2156. /* See if it's time for the account to be unlocked */
  2157. char *unlock_time_str = NULL;
  2158. char *cur_time_str = NULL;
  2159. time_t _unlock_time = (time_t)0;
  2160. time_t cur_time;
  2161. unlock_time_str = slapi_entry_attr_get_charptr(e, "accountUnlockTime");
  2162. if (unlock_time_str) {
  2163. _unlock_time = parse_genTime(unlock_time_str);
  2164. }
  2165. if ((pwpolicy->pw_unlock == 0) && (_unlock_time == NO_TIME)) {
  2166. /* Account is locked forever */
  2167. if (unlock_time) {
  2168. *unlock_time = (time_t)0;
  2169. }
  2170. } else {
  2171. cur_time = current_time();
  2172. cur_time_str = format_genTime(cur_time);
  2173. if (difftime(parse_genTime(cur_time_str), _unlock_time) < 0) {
  2174. /* Account is not due to be unlocked yet.
  2175. * Fill in the unlock time. */
  2176. if (unlock_time) {
  2177. *unlock_time = _unlock_time;
  2178. }
  2179. } else {
  2180. /* Account is due to be unlocked */
  2181. is_locked = 0;
  2182. }
  2183. slapi_ch_free_string(&cur_time_str);
  2184. }
  2185. }
  2186. }
  2187. return is_locked;
  2188. }
  2189. int
  2190. slapi_pwpolicy_is_reset(Slapi_PWPolicy *pwpolicy, Slapi_Entry *e)
  2191. {
  2192. int is_reset = 0;
  2193. if (pwpolicy && e) {
  2194. /* Check if password was reset and needs to be changed */
  2195. if (pwpolicy->pw_must_change) {
  2196. char *expiration_val = 0;
  2197. time_t expire_time = (time_t)0;
  2198. expiration_val = slapi_entry_attr_get_charptr(e, "passwordExpirationTime");
  2199. if (expiration_val) {
  2200. expire_time = parse_genTime(expiration_val);
  2201. if (expire_time == NO_TIME) {
  2202. is_reset = 1;
  2203. }
  2204. }
  2205. }
  2206. }
  2207. return is_reset;
  2208. }
  2209. /*
  2210. * Entry extension for unhashed password
  2211. */
  2212. static int pw_entry_objtype = -1;
  2213. static int pw_entry_handle = -1;
  2214. struct slapi_pw_entry_ext {
  2215. Slapi_RWLock *pw_entry_lock; /* necessary? */
  2216. Slapi_Value **pw_entry_values; /* stashed values */
  2217. };
  2218. /*
  2219. * constructor for the entry object extension.
  2220. */
  2221. static void *
  2222. pw_entry_constructor(void *object, void *parent)
  2223. {
  2224. struct slapi_pw_entry_ext *pw_extp = NULL;
  2225. Slapi_RWLock *rwlock;
  2226. if ((rwlock = slapi_new_rwlock()) == NULL) {
  2227. slapi_log_error(SLAPI_LOG_FATAL, NULL,
  2228. "pw_entry_constructor: slapi_new_rwlock() failed\n");
  2229. slapi_log_error(SLAPI_LOG_FATAL, NULL,
  2230. "WARNING: the server cannot handle unhashed password.\n");
  2231. return NULL;
  2232. }
  2233. pw_extp = (struct slapi_pw_entry_ext *)slapi_ch_calloc(1,
  2234. sizeof(struct slapi_pw_entry_ext));
  2235. pw_extp->pw_entry_lock = rwlock;
  2236. return pw_extp;
  2237. }
  2238. /*
  2239. * destructor for the entry object extension.
  2240. */
  2241. static void
  2242. pw_entry_destructor(void *extension, void *object, void *parent)
  2243. {
  2244. struct slapi_pw_entry_ext *pw_extp = (struct slapi_pw_entry_ext *)extension;
  2245. if (NULL == pw_extp) {
  2246. return;
  2247. }
  2248. valuearray_free(&pw_extp->pw_entry_values);
  2249. if (pw_extp->pw_entry_lock) {
  2250. slapi_destroy_rwlock(pw_extp->pw_entry_lock);
  2251. }
  2252. slapi_ch_free((void **)&pw_extp);
  2253. }
  2254. /* Called once from main */
  2255. void
  2256. pw_exp_init ( void )
  2257. {
  2258. if (slapi_register_object_extension(SLAPI_EXTMOD_PWPOLICY,
  2259. SLAPI_EXT_ENTRY,
  2260. pw_entry_constructor,
  2261. pw_entry_destructor,
  2262. &pw_entry_objtype,
  2263. &pw_entry_handle) != 0) {
  2264. slapi_log_error(SLAPI_LOG_FATAL, NULL,
  2265. "pw_init: slapi_register_object_extension failed; "
  2266. "unhashed password is not able to access\n");
  2267. }
  2268. }
  2269. /*
  2270. * The output value vals is not a copy.
  2271. * Caller must duplicate it to use it for other than referring.
  2272. */
  2273. int
  2274. slapi_pw_get_entry_ext(Slapi_Entry *entry, Slapi_Value ***vals)
  2275. {
  2276. struct slapi_pw_entry_ext *extp = NULL;
  2277. if (NULL == vals) {
  2278. slapi_log_error(SLAPI_LOG_FATAL, NULL,
  2279. "slapi_pw_get_entry_ext: output param vals is NULL.\n");
  2280. return LDAP_PARAM_ERROR;
  2281. }
  2282. *vals = NULL;
  2283. if ((-1 == pw_entry_objtype) || (-1 == pw_entry_handle)) {
  2284. slapi_log_error(SLAPI_LOG_TRACE, NULL,
  2285. "slapi_pw_get_entry_ext: pw_entry_extension is not "
  2286. "registered\n");
  2287. return LDAP_OPERATIONS_ERROR;
  2288. }
  2289. extp = (struct slapi_pw_entry_ext *)slapi_get_object_extension(
  2290. pw_entry_objtype,
  2291. entry,
  2292. pw_entry_handle);
  2293. if ((NULL == extp) || (NULL == extp->pw_entry_values)) {
  2294. slapi_log_error(SLAPI_LOG_TRACE, NULL,
  2295. "slapi_pw_get_entry_ext: "
  2296. "pw_entry_extension is not set\n");
  2297. return LDAP_NO_SUCH_ATTRIBUTE;
  2298. }
  2299. slapi_rwlock_rdlock(extp->pw_entry_lock);
  2300. *vals = extp->pw_entry_values;
  2301. slapi_rwlock_unlock(extp->pw_entry_lock);
  2302. return LDAP_SUCCESS;
  2303. }
  2304. /* If vals is NULL, the stored extension is freed. */
  2305. /* If slapi_pw_set_entry_ext is successful, vals are consumed. */
  2306. int
  2307. slapi_pw_set_entry_ext(Slapi_Entry *entry, Slapi_Value **vals, int flags)
  2308. {
  2309. struct slapi_pw_entry_ext *extp = NULL;
  2310. if ((-1 == pw_entry_objtype) || (-1 == pw_entry_handle)) {
  2311. slapi_log_error(SLAPI_LOG_TRACE, NULL,
  2312. "slapi_pw_set_entry_ext: "
  2313. "pw_entry_extension is not registered\n");
  2314. return LDAP_OPERATIONS_ERROR;
  2315. }
  2316. extp = (struct slapi_pw_entry_ext *)slapi_get_object_extension(
  2317. pw_entry_objtype,
  2318. entry,
  2319. pw_entry_handle);
  2320. if (NULL == extp) {
  2321. slapi_log_error(SLAPI_LOG_TRACE, NULL,
  2322. "slapi_pw_set_entry_ext: "
  2323. "pw_entry_extension is not set\n");
  2324. return LDAP_NO_SUCH_ATTRIBUTE;
  2325. }
  2326. slapi_rwlock_wrlock(extp->pw_entry_lock);
  2327. if (NULL == vals) { /* Set NULL; used for delete. */
  2328. valuearray_free(&extp->pw_entry_values); /* Null is taken care */
  2329. } else {
  2330. if (SLAPI_EXT_SET_REPLACE == flags) {
  2331. valuearray_free(&extp->pw_entry_values); /* Null is taken care */
  2332. }
  2333. /* Each (Slapi_Value *) in vals is passed in. */
  2334. valuearray_add_valuearray(&extp->pw_entry_values, vals,
  2335. SLAPI_VALUE_FLAG_PASSIN);
  2336. /* To keep the word "consumed", free vals part, as well. */
  2337. slapi_ch_free((void **)&vals);
  2338. }
  2339. slapi_rwlock_unlock(extp->pw_entry_lock);
  2340. return LDAP_SUCCESS;
  2341. }
  2342. int
  2343. pw_copy_entry_ext(Slapi_Entry *src_e, Slapi_Entry *dest_e)
  2344. {
  2345. struct slapi_pw_entry_ext *src_extp = NULL;
  2346. struct slapi_pw_entry_ext *dest_extp = NULL;
  2347. if ((-1 == pw_entry_objtype) || (-1 == pw_entry_handle)) {
  2348. slapi_log_error(SLAPI_LOG_TRACE, NULL,
  2349. "pw_copy_entry_ext: "
  2350. "pw_entry_extension is not registered\n");
  2351. return LDAP_OPERATIONS_ERROR;
  2352. }
  2353. src_extp = (struct slapi_pw_entry_ext *)slapi_get_object_extension(
  2354. pw_entry_objtype,
  2355. src_e,
  2356. pw_entry_handle);
  2357. if (NULL == src_extp) {
  2358. slapi_log_error(SLAPI_LOG_TRACE, NULL,
  2359. "pw_copy_entry_ext: source pw_entry_extension is "
  2360. "not set\n");
  2361. return LDAP_NO_SUCH_ATTRIBUTE;
  2362. }
  2363. slapi_rwlock_rdlock(src_extp->pw_entry_lock);
  2364. dest_extp = (struct slapi_pw_entry_ext *)slapi_get_object_extension(
  2365. pw_entry_objtype,
  2366. dest_e,
  2367. pw_entry_handle);
  2368. if (NULL == dest_extp) {
  2369. slapi_rwlock_unlock(src_extp->pw_entry_lock);
  2370. slapi_log_error(SLAPI_LOG_TRACE, NULL,
  2371. "pw_copy_entry_ext: "
  2372. "dest pw_entry_extension is not set\n");
  2373. return LDAP_NO_SUCH_ATTRIBUTE;
  2374. }
  2375. slapi_rwlock_wrlock(dest_extp->pw_entry_lock);
  2376. valuearray_add_valuearray(&dest_extp->pw_entry_values,
  2377. src_extp->pw_entry_values, 0);
  2378. slapi_rwlock_unlock(dest_extp->pw_entry_lock);
  2379. slapi_rwlock_unlock(src_extp->pw_entry_lock);
  2380. return LDAP_SUCCESS;
  2381. }
  2382. /*
  2383. * The returned string is a copy.
  2384. * Caller must free it.
  2385. */
  2386. char *
  2387. slapi_get_first_clear_text_pw(Slapi_Entry *entry)
  2388. {
  2389. struct slapi_pw_entry_ext *extp = NULL;
  2390. Slapi_Value **pwvals = NULL;
  2391. const char *password_str = NULL;
  2392. if ((-1 == pw_entry_objtype) || (-1 == pw_entry_handle)) {
  2393. slapi_log_error(SLAPI_LOG_TRACE, NULL,
  2394. "slapi_get_first_clear_text_pw: "
  2395. "pw_entry_extension is not registered\n");
  2396. return NULL;
  2397. }
  2398. extp = (struct slapi_pw_entry_ext *)slapi_get_object_extension(
  2399. pw_entry_objtype,
  2400. entry,
  2401. pw_entry_handle);
  2402. if ((NULL == extp) || (NULL == extp->pw_entry_values)) {
  2403. slapi_log_error(SLAPI_LOG_TRACE, NULL,
  2404. "slapi_get_first_clear_text_pw: "
  2405. "pw_entry_extension is not set\n");
  2406. return NULL;
  2407. }
  2408. slapi_rwlock_rdlock(extp->pw_entry_lock);
  2409. pwvals = extp->pw_entry_values;
  2410. if (pwvals) {
  2411. Slapi_ValueSet vset;
  2412. Slapi_Value *value = NULL;
  2413. /* pwvals is passed in to vset; thus no need to free vset. */
  2414. valueset_set_valuearray_passin(&vset, pwvals);
  2415. slapi_valueset_first_value(&vset, &value);
  2416. password_str = slapi_value_get_string(value);
  2417. }
  2418. slapi_rwlock_unlock(extp->pw_entry_lock);
  2419. return slapi_ch_strdup(password_str); /* slapi_ch_strdup(NULL) is okay */
  2420. }
  2421. void
  2422. slapi_free_pw_scheme(struct pw_scheme *pwsp)
  2423. {
  2424. free_pw_scheme(pwsp);
  2425. }
  2426. struct pw_scheme *
  2427. slapi_pw_val2scheme( char *val, char **valpwdp, int first_is_default )
  2428. {
  2429. return pw_val2scheme( val, valpwdp, first_is_default );
  2430. }
  2431. int
  2432. slapi_pw_cmp(struct pw_scheme *pass_scheme, char *clear_pw, char *encoded_pw)
  2433. {
  2434. return ((*(pass_scheme->pws_cmp))( clear_pw, encoded_pw ));
  2435. }
  2436. char *
  2437. slapi_pw_get_scheme_name(struct pw_scheme *pass_scheme)
  2438. {
  2439. return pass_scheme->pws_name;
  2440. }
  2441. int
  2442. pw_get_ext_size(Slapi_Entry *entry, size_t *size)
  2443. {
  2444. Slapi_Value **pw_entry_values;
  2445. if (NULL == size) {
  2446. return LDAP_PARAM_ERROR;
  2447. }
  2448. *size = 0;
  2449. if (NULL == entry->e_extension) {
  2450. return LDAP_SUCCESS;
  2451. }
  2452. *size += sizeof(struct slapi_pw_entry_ext);
  2453. *size += sizeof(Slapi_RWLock);
  2454. if (LDAP_SUCCESS == slapi_pw_get_entry_ext(entry, &pw_entry_values)) {
  2455. Slapi_Value *cvalue;
  2456. int idx = valuearray_first_value(pw_entry_values, &cvalue);
  2457. while (idx >= 0) {
  2458. *size += value_size(cvalue);
  2459. idx = valuearray_next_value(pw_entry_values, idx, &cvalue);
  2460. }
  2461. }
  2462. return LDAP_SUCCESS;
  2463. }