pw_retry.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. /* pw_retry.c
  13. */
  14. #include <time.h>
  15. #include "slap.h"
  16. /****************************************************************************/
  17. /* prototypes */
  18. /****************************************************************************/
  19. /* Slapi_Entry *get_entry ( Slapi_PBlock *pb, const char *dn ); */
  20. static int set_retry_cnt ( Slapi_PBlock *pb, int count);
  21. static int set_retry_cnt_and_time ( Slapi_PBlock *pb, int count, time_t cur_time);
  22. /*
  23. * update_pw_retry() is called when bind operation fails
  24. * with LDAP_INVALID_CREDENTIALS (in backend bind.c ).
  25. * It checks to see if the retry count can be reset,
  26. * increments retry count, and then check if need to lock the acount.
  27. * To have a global password policy, these mods should be chained to the
  28. * master, and not applied locally. If they are applied locally, they should
  29. * not get replicated from master...
  30. */
  31. int update_pw_retry ( Slapi_PBlock *pb )
  32. {
  33. Slapi_Entry *e;
  34. int retry_cnt=0;
  35. time_t reset_time;
  36. time_t cur_time;
  37. char *cur_time_str = NULL;
  38. char *retryCountResetTime;
  39. int passwordRetryCount;
  40. int rc = 0;
  41. /* get the entry */
  42. e = get_entry ( pb, NULL );
  43. if ( e == NULL ) {
  44. return ( 1 );
  45. }
  46. cur_time = current_time();
  47. /* check if the retry count can be reset. */
  48. retryCountResetTime= slapi_entry_attr_get_charptr(e, "retryCountResetTime");
  49. if(retryCountResetTime!=NULL)
  50. {
  51. reset_time = parse_genTime (retryCountResetTime);
  52. slapi_ch_free((void **) &retryCountResetTime );
  53. cur_time_str = format_genTime ( cur_time );
  54. if ( difftime ( parse_genTime( cur_time_str ), reset_time) >= 0 )
  55. {
  56. /* set passwordRetryCount to 1 */
  57. /* reset retryCountResetTime */
  58. rc = set_retry_cnt_and_time ( pb, 1, cur_time );
  59. slapi_ch_free((void **) &cur_time_str );
  60. slapi_entry_free( e );
  61. return ( rc ); /* success */
  62. } else {
  63. slapi_ch_free((void **) &cur_time_str );
  64. }
  65. } else {
  66. /* initialize passwordRetryCount and retryCountResetTime */
  67. rc = set_retry_cnt_and_time ( pb, 1, cur_time );
  68. slapi_entry_free( e );
  69. return ( rc ); /* success */
  70. }
  71. passwordRetryCount = slapi_entry_attr_get_int(e, "passwordRetryCount");
  72. if (passwordRetryCount >= 0)
  73. {
  74. retry_cnt = passwordRetryCount + 1;
  75. if ( retry_cnt == 1 ) {
  76. /* set retryCountResetTime */
  77. rc = set_retry_cnt_and_time ( pb, retry_cnt, cur_time );
  78. } else {
  79. /* set passwordRetryCount to retry_cnt */
  80. rc = set_retry_cnt ( pb, retry_cnt );
  81. }
  82. }
  83. slapi_entry_free( e );
  84. return rc; /* success */
  85. }
  86. static
  87. int set_retry_cnt_and_time ( Slapi_PBlock *pb, int count, time_t cur_time ) {
  88. const char *dn = NULL;
  89. Slapi_DN *sdn = NULL;
  90. Slapi_Mods smods;
  91. time_t reset_time;
  92. char *timestr;
  93. passwdPolicy *pwpolicy = NULL;
  94. int rc = 0;
  95. slapi_pblock_get( pb, SLAPI_TARGET_SDN, &sdn );
  96. dn = slapi_sdn_get_dn(sdn);
  97. pwpolicy = new_passwdPolicy(pb, dn);
  98. slapi_mods_init(&smods, 0);
  99. reset_time = time_plus_sec ( cur_time,
  100. pwpolicy->pw_resetfailurecount );
  101. timestr = format_genTime ( reset_time );
  102. slapi_mods_add_string(&smods, LDAP_MOD_REPLACE, "retryCountResetTime", timestr);
  103. slapi_ch_free((void **)&timestr);
  104. rc = set_retry_cnt_mods(pb, &smods, count);
  105. pw_apply_mods(sdn, &smods);
  106. slapi_mods_done(&smods);
  107. return rc;
  108. }
  109. int set_retry_cnt_mods(Slapi_PBlock *pb, Slapi_Mods *smods, int count)
  110. {
  111. char *timestr;
  112. time_t unlock_time;
  113. char retry_cnt[8]; /* 1-65535 */
  114. const char *dn = NULL;
  115. Slapi_DN *sdn = NULL;
  116. passwdPolicy *pwpolicy = NULL;
  117. int rc = 0;
  118. slapi_pblock_get( pb, SLAPI_TARGET_SDN, &sdn );
  119. dn = slapi_sdn_get_dn(sdn);
  120. pwpolicy = new_passwdPolicy(pb, dn);
  121. if (smods) {
  122. sprintf ( retry_cnt, "%d", count );
  123. slapi_mods_add_string(smods, LDAP_MOD_REPLACE, "passwordRetryCount", retry_cnt);
  124. /* lock account if reache retry limit */
  125. if ( count >= pwpolicy->pw_maxfailure ) {
  126. /* Remove lock_account function to perform all mods at once */
  127. /* lock_account ( pb ); */
  128. /* reach the retry limit, lock the account */
  129. if ( pwpolicy->pw_unlock == 0 ) {
  130. /* lock until admin reset password */
  131. unlock_time = NO_TIME;
  132. } else {
  133. unlock_time = time_plus_sec ( current_time(),
  134. pwpolicy->pw_lockduration );
  135. }
  136. timestr= format_genTime ( unlock_time );
  137. slapi_mods_add_string(smods, LDAP_MOD_REPLACE, "accountUnlockTime", timestr);
  138. slapi_ch_free((void **)&timestr);
  139. rc = LDAP_CONSTRAINT_VIOLATION;
  140. }
  141. }
  142. return rc;
  143. }
  144. static
  145. int set_retry_cnt ( Slapi_PBlock *pb, int count)
  146. {
  147. Slapi_DN *sdn = NULL;
  148. Slapi_Mods smods;
  149. int rc = 0;
  150. slapi_pblock_get( pb, SLAPI_TARGET_SDN, &sdn );
  151. slapi_mods_init(&smods, 0);
  152. rc = set_retry_cnt_mods(pb, &smods, count);
  153. pw_apply_mods(sdn, &smods);
  154. slapi_mods_done(&smods);
  155. return rc;
  156. }
  157. /*
  158. * If "dn" is passed, get_entry returns an entry which dn is "dn".
  159. * If "dn" is not passed, it returns an entry which dn is set in
  160. * SLAPI_TARGET_SDN in pblock.
  161. * Note: pblock is not mandatory for get_entry (e.g., new_passwdPolicy).
  162. */
  163. Slapi_Entry *get_entry ( Slapi_PBlock *pb, const char *dn)
  164. {
  165. int search_result = 0;
  166. Slapi_Entry *retentry = NULL;
  167. Slapi_DN *target_sdn = NULL;
  168. const char *target_dn = dn;
  169. Slapi_DN sdn;
  170. if (pb) {
  171. slapi_pblock_get( pb, SLAPI_TARGET_SDN, &target_sdn );
  172. if (target_dn == NULL) {
  173. target_dn = slapi_sdn_get_dn(target_sdn);
  174. }
  175. }
  176. if (target_dn == NULL) {
  177. LDAPDebug0Args(LDAP_DEBUG_TRACE,
  178. "WARNING: 'get_entry' - no dn specified.\n");
  179. goto bail;
  180. }
  181. if (target_dn == dn) { /* target_dn is NOT from target_sdn */
  182. slapi_sdn_init_dn_byref(&sdn, target_dn);
  183. target_sdn = &sdn;
  184. }
  185. search_result = slapi_search_internal_get_entry(target_sdn, NULL,
  186. &retentry,
  187. pw_get_componentID());
  188. if (search_result != LDAP_SUCCESS) {
  189. LDAPDebug2Args(LDAP_DEBUG_TRACE,
  190. "WARNING: 'get_entry' can't find entry '%s', err %d\n",
  191. target_dn, search_result);
  192. }
  193. if (target_dn == dn) { /* target_dn is NOT from target_sdn */
  194. slapi_sdn_done(&sdn);
  195. }
  196. bail:
  197. return retentry;
  198. }
  199. void
  200. pw_apply_mods(const Slapi_DN *sdn, Slapi_Mods *mods)
  201. {
  202. Slapi_PBlock pb;
  203. int res;
  204. if (mods && (slapi_mods_get_num_mods(mods) > 0))
  205. {
  206. pblock_init(&pb);
  207. /* We don't want to overwrite the modifiersname, etc. attributes,
  208. * so we set a flag for this operation */
  209. slapi_modify_internal_set_pb_ext (&pb, sdn,
  210. slapi_mods_get_ldapmods_byref(mods),
  211. NULL, /* Controls */
  212. NULL, /* UniqueID */
  213. pw_get_componentID(), /* PluginID */
  214. OP_FLAG_SKIP_MODIFIED_ATTRS); /* Flags */
  215. slapi_modify_internal_pb (&pb);
  216. slapi_pblock_get(&pb, SLAPI_PLUGIN_INTOP_RESULT, &res);
  217. if (res != LDAP_SUCCESS){
  218. LDAPDebug2Args(LDAP_DEBUG_ANY,
  219. "WARNING: passwordPolicy modify error %d on entry '%s'\n",
  220. res, slapi_sdn_get_dn(sdn));
  221. }
  222. pblock_done(&pb);
  223. }
  224. return;
  225. }
  226. /* Handle the component ID for the password policy */
  227. static struct slapi_componentid * pw_componentid = NULL;
  228. void pw_set_componentID(struct slapi_componentid *cid)
  229. {
  230. pw_componentid = cid;
  231. }
  232. struct slapi_componentid * pw_get_componentID()
  233. {
  234. return pw_componentid;
  235. }