retrocl.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  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. /*
  13. * Requires that create_instance.c have added a plugin entry similar to:
  14. dn: cn=Retrocl Plugin,cn=plugins,cn=config
  15. objectclass: top
  16. objectclass: nsSlapdPlugin
  17. objectclass: extensibleObject
  18. cn: RetroCL Plugin
  19. nsslapd-pluginpath: /export2/servers/Hydra-supplier/lib/retrocl-plugin.so
  20. nsslapd-plugininitfunc: retrocl_plugin_init
  21. nsslapd-plugintype: object
  22. nsslapd-pluginenabled: on
  23. nsslapd-plugin-depends-on-type: database
  24. nsslapd-pluginid: retrocl
  25. nsslapd-pluginversion: 5.0b2
  26. nsslapd-pluginvendor: Sun Microsystems, Inc.
  27. nsslapd-plugindescription: Retrocl Plugin
  28. *
  29. */
  30. #include "retrocl.h"
  31. void* g_plg_identity [PLUGIN_MAX];
  32. Slapi_Backend *retrocl_be_changelog = NULL;
  33. PRLock *retrocl_internal_lock = NULL;
  34. Slapi_RWLock *retrocl_cn_lock;
  35. int retrocl_nattributes = 0;
  36. char **retrocl_attributes = NULL;
  37. char **retrocl_aliases = NULL;
  38. int retrocl_log_deleted = 0;
  39. static Slapi_DN **retrocl_includes = NULL;
  40. static Slapi_DN **retrocl_excludes = NULL;
  41. /* ----------------------------- Retrocl Plugin */
  42. static Slapi_PluginDesc retrocldesc = {"retrocl", VENDOR, DS_PACKAGE_VERSION, "Retrocl Plugin"};
  43. static Slapi_PluginDesc retroclpostopdesc = {"retrocl-postop", VENDOR, DS_PACKAGE_VERSION, "retrocl post-operation plugin"};
  44. static Slapi_PluginDesc retroclinternalpostopdesc = {"retrocl-internalpostop", VENDOR, DS_PACKAGE_VERSION, "retrocl internal post-operation plugin"};
  45. static int legacy_initialised= 0;
  46. /*
  47. * Function: retrocl_*
  48. *
  49. * Returns: LDAP_
  50. *
  51. * Arguments: Pb of operation
  52. *
  53. * Description: wrappers around retrocl_postob registered as callback
  54. *
  55. */
  56. int retrocl_postop_add (Slapi_PBlock *pb) { return retrocl_postob(pb,OP_ADD);}
  57. int retrocl_postop_delete (Slapi_PBlock *pb) { return retrocl_postob(pb,OP_DELETE);}
  58. int retrocl_postop_modify (Slapi_PBlock *pb) { return retrocl_postob(pb,OP_MODIFY);}
  59. int retrocl_postop_modrdn (Slapi_PBlock *pb) { return retrocl_postob(pb,OP_MODRDN);}
  60. /*
  61. * Function: retrocl_postop_init
  62. *
  63. * Returns: 0/-1
  64. *
  65. * Arguments: Pb
  66. *
  67. * Description: callback function
  68. *
  69. */
  70. int
  71. retrocl_postop_init( Slapi_PBlock *pb )
  72. {
  73. int rc= 0; /* OK */
  74. Slapi_Entry *plugin_entry = NULL;
  75. char *plugin_type = NULL;
  76. int postadd = SLAPI_PLUGIN_POST_ADD_FN;
  77. int postmod = SLAPI_PLUGIN_POST_MODIFY_FN;
  78. int postmdn = SLAPI_PLUGIN_POST_MODRDN_FN;
  79. int postdel = SLAPI_PLUGIN_POST_DELETE_FN;
  80. if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry) == 0) &&
  81. plugin_entry &&
  82. (plugin_type = slapi_entry_attr_get_charptr(plugin_entry, "nsslapd-plugintype")) &&
  83. plugin_type && strstr(plugin_type, "betxn")) {
  84. postadd = SLAPI_PLUGIN_BE_TXN_POST_ADD_FN;
  85. postmod = SLAPI_PLUGIN_BE_TXN_POST_MODIFY_FN;
  86. postmdn = SLAPI_PLUGIN_BE_TXN_POST_MODRDN_FN;
  87. postdel = SLAPI_PLUGIN_BE_TXN_POST_DELETE_FN;
  88. }
  89. slapi_ch_free_string(&plugin_type);
  90. if( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 ) != 0 ||
  91. slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&retroclpostopdesc ) != 0 ||
  92. slapi_pblock_set( pb, postadd, (void *) retrocl_postop_add ) != 0 ||
  93. slapi_pblock_set( pb, postdel, (void *) retrocl_postop_delete ) != 0 ||
  94. slapi_pblock_set( pb, postmod, (void *) retrocl_postop_modify ) != 0 ||
  95. slapi_pblock_set( pb, postmdn, (void *) retrocl_postop_modrdn ) != 0 )
  96. {
  97. slapi_log_error( SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME, "retrocl_postop_init failed\n" );
  98. rc= -1;
  99. }
  100. return rc;
  101. }
  102. /*
  103. * Function: retrocl_internalpostop_init
  104. *
  105. * Returns: 0/-1
  106. *
  107. * Arguments: Pb
  108. *
  109. * Description: callback function
  110. *
  111. */
  112. int
  113. retrocl_internalpostop_init( Slapi_PBlock *pb )
  114. {
  115. int rc= 0; /* OK */
  116. if( slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 ) != 0 ||
  117. slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&retroclinternalpostopdesc ) != 0 ||
  118. slapi_pblock_set( pb, SLAPI_PLUGIN_INTERNAL_POST_ADD_FN, (void *) retrocl_postop_add ) != 0 ||
  119. slapi_pblock_set( pb, SLAPI_PLUGIN_INTERNAL_POST_DELETE_FN, (void *) retrocl_postop_delete ) != 0 ||
  120. slapi_pblock_set( pb, SLAPI_PLUGIN_INTERNAL_POST_MODIFY_FN, (void *) retrocl_postop_modify ) != 0 ||
  121. slapi_pblock_set( pb, SLAPI_PLUGIN_INTERNAL_POST_MODRDN_FN, (void *) retrocl_postop_modrdn ) != 0 )
  122. {
  123. slapi_log_error( SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME, "retrocl_internalpostop_init failed\n" );
  124. rc= -1;
  125. }
  126. return rc;
  127. }
  128. /*
  129. * Function: retrocl_rootdse_init
  130. *
  131. * Returns: LDAP_SUCCESS
  132. *
  133. * Arguments: Slapi_PBlock
  134. *
  135. * Description: The FE DSE *must* be initialised before we get here.
  136. *
  137. */
  138. static int retrocl_rootdse_init(Slapi_PBlock *pb)
  139. {
  140. int return_value= LDAP_SUCCESS;
  141. slapi_config_register_callback_plugin(SLAPI_OPERATION_SEARCH,DSE_FLAG_PREOP | DSE_FLAG_PLUGIN, "",
  142. LDAP_SCOPE_BASE,"(objectclass=*)",
  143. retrocl_rootdse_search, NULL, pb);
  144. return return_value;
  145. }
  146. /*
  147. * Function: retrocl_select_backend
  148. *
  149. * Returns: LDAP_
  150. *
  151. * Arguments: none
  152. *
  153. * Description: simulates an add of the changelog to see if it exists. If not,
  154. * creates it. Then reads the changenumbers. This function should be called
  155. * exactly once at startup.
  156. *
  157. */
  158. static int retrocl_select_backend(void)
  159. {
  160. int err;
  161. Slapi_PBlock *pb;
  162. Slapi_Backend *be = NULL;
  163. Slapi_Entry *referral = NULL;
  164. Slapi_Operation *op = NULL;
  165. char errbuf[BUFSIZ];
  166. pb = slapi_pblock_new();
  167. slapi_pblock_set (pb, SLAPI_PLUGIN_IDENTITY, g_plg_identity[PLUGIN_RETROCL]);
  168. /* This is a simulated operation; no actual add is performed */
  169. op = operation_new(OP_FLAG_INTERNAL);
  170. operation_set_type(op,SLAPI_OPERATION_ADD); /* Ensure be not readonly */
  171. operation_set_target_spec_str(op,RETROCL_CHANGELOG_DN);
  172. slapi_pblock_set(pb,SLAPI_OPERATION, op);
  173. err = slapi_mapping_tree_select(pb,&be,&referral,errbuf);
  174. slapi_entry_free(referral);
  175. if (err != LDAP_SUCCESS || be == NULL || be == defbackend_get_backend()) {
  176. LDAPDebug2Args(LDAP_DEBUG_TRACE,"Mapping tree select failed (%d) %s.\n",
  177. err,errbuf);
  178. /* could not find the backend for cn=changelog, either because
  179. * it doesn't exist
  180. * mapping tree not registered.
  181. */
  182. err = retrocl_create_config();
  183. if (err != LDAP_SUCCESS) return err;
  184. } else {
  185. retrocl_be_changelog = be;
  186. }
  187. retrocl_create_cle();
  188. slapi_pblock_destroy(pb);
  189. if (be)
  190. slapi_be_Unlock(be);
  191. return retrocl_get_changenumbers();
  192. }
  193. /*
  194. * Function: retrocl_get_config_str
  195. *
  196. * Returns: malloc'ed string which must be freed.
  197. *
  198. * Arguments: attribute type name
  199. *
  200. * Description: reads a single-valued string attr from the plugins' own DSE.
  201. * This is called twice: to obtain the trim max age during startup, and to
  202. * obtain the change log directory. No callback is registered; you cannot
  203. * change the trim max age without restarting the server.
  204. *
  205. */
  206. char *retrocl_get_config_str(const char *attrt)
  207. {
  208. Slapi_Entry **entries;
  209. Slapi_PBlock *pb = NULL;
  210. char *ma;
  211. int rc = 0;
  212. char *dn;
  213. /* RETROCL_PLUGIN_DN is no need to be normalized. */
  214. dn = RETROCL_PLUGIN_DN;
  215. pb = slapi_pblock_new();
  216. slapi_search_internal_set_pb (pb, dn, LDAP_SCOPE_BASE, "objectclass=*", NULL, 0, NULL,
  217. NULL, g_plg_identity[PLUGIN_RETROCL] , 0);
  218. slapi_search_internal_pb (pb);
  219. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
  220. if (rc != 0) {
  221. slapi_pblock_destroy(pb);
  222. return NULL;
  223. }
  224. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
  225. ma = slapi_entry_attr_get_charptr(entries[0],attrt);
  226. slapi_free_search_results_internal(pb);
  227. slapi_pblock_destroy(pb);
  228. return ma;
  229. }
  230. static void
  231. retrocl_remove_legacy_default_aci(void)
  232. {
  233. Slapi_PBlock *pb = NULL;
  234. Slapi_Entry **entries;
  235. char **aci_vals = NULL;
  236. char *attrs[] = {"aci", NULL};
  237. int rc;
  238. pb = slapi_pblock_new();
  239. slapi_search_internal_set_pb(pb, RETROCL_CHANGELOG_DN, LDAP_SCOPE_BASE, "objectclass=*",
  240. attrs, 0, NULL, NULL, g_plg_identity[PLUGIN_RETROCL] , 0);
  241. slapi_search_internal_pb(pb);
  242. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
  243. if (rc == LDAP_SUCCESS) {
  244. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
  245. if(entries && entries[0]){
  246. if((aci_vals = slapi_entry_attr_get_charray(entries[0], "aci"))){
  247. if(charray_inlist(aci_vals, RETROCL_ACL)){
  248. /*
  249. * Okay, we need to remove the aci
  250. */
  251. LDAPMod mod;
  252. LDAPMod *mods[2];
  253. char *val[2];
  254. Slapi_PBlock *mod_pb = 0;
  255. mod_pb = slapi_pblock_new();
  256. mods[0] = &mod;
  257. mods[1] = 0;
  258. val[0] = RETROCL_ACL;
  259. val[1] = 0;
  260. mod.mod_op = LDAP_MOD_DELETE;
  261. mod.mod_type = "aci";
  262. mod.mod_values = val;
  263. slapi_modify_internal_set_pb_ext(mod_pb, slapi_entry_get_sdn(entries[0]),
  264. mods, 0, 0, g_plg_identity[PLUGIN_RETROCL], 0);
  265. slapi_modify_internal_pb(mod_pb);
  266. slapi_pblock_get(mod_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
  267. if(rc == LDAP_SUCCESS){
  268. slapi_log_error( SLAPI_LOG_FATAL, RETROCL_PLUGIN_NAME,
  269. "Successfully removed vulnerable legacy default aci \"%s\". "
  270. "If the aci removal was not desired please use a different \"acl "
  271. "name\" so it is not removed at the next plugin startup.\n",
  272. RETROCL_ACL);
  273. } else {
  274. slapi_log_error( SLAPI_LOG_FATAL, RETROCL_PLUGIN_NAME,
  275. "Failed to removed vulnerable legacy default aci (%s) error %d\n",
  276. RETROCL_ACL, rc);
  277. }
  278. slapi_pblock_destroy(mod_pb);
  279. }
  280. slapi_ch_array_free(aci_vals);
  281. }
  282. }
  283. }
  284. slapi_free_search_results_internal(pb);
  285. slapi_pblock_destroy(pb);
  286. }
  287. /*
  288. * Function: retrocl_start
  289. *
  290. * Returns: 0 on success
  291. *
  292. * Arguments: Pb
  293. *
  294. * Description:
  295. *
  296. */
  297. static int retrocl_start (Slapi_PBlock *pb)
  298. {
  299. int rc = 0;
  300. Slapi_Entry *e = NULL;
  301. char **values = NULL;
  302. int num_vals = 0;
  303. int i = 0;
  304. retrocl_rootdse_init(pb);
  305. rc = retrocl_select_backend();
  306. if (rc != 0) {
  307. LDAPDebug1Arg(LDAP_DEBUG_TRACE,"Couldnt find backend, not trimming retro changelog (%d).\n",rc);
  308. return rc;
  309. }
  310. /* Remove the old default aci as it exposes passwords changes to anonymous users */
  311. retrocl_remove_legacy_default_aci();
  312. retrocl_init_trimming();
  313. if (slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e) != 0) {
  314. slapi_log_error(SLAPI_LOG_FATAL, RETROCL_PLUGIN_NAME, "Missing config entry.\n");
  315. return -1;
  316. }
  317. /* Get the exclude suffixes */
  318. values = slapi_entry_attr_get_charray_ext(e, CONFIG_CHANGELOG_EXCLUDE_SUFFIX, &num_vals);
  319. if(values){
  320. /* Validate the syntax before we create our DN array */
  321. for (i = 0;i < num_vals; i++){
  322. if(slapi_dn_syntax_check(pb, values[i], 1)){
  323. /* invalid dn syntax */
  324. slapi_log_error(SLAPI_LOG_FATAL, RETROCL_PLUGIN_NAME,
  325. "Invalid DN (%s) for exclude suffix.\n", values[i] );
  326. slapi_ch_array_free(values);
  327. return -1;
  328. }
  329. }
  330. /* Now create our SDN array */
  331. retrocl_excludes = (Slapi_DN **)slapi_ch_calloc(sizeof(Slapi_DN *),num_vals+1);
  332. for (i = 0;i < num_vals; i++){
  333. retrocl_excludes[i] = slapi_sdn_new_dn_byval(values[i]);
  334. }
  335. slapi_ch_array_free(values);
  336. }
  337. /* Get the include suffixes */
  338. values = slapi_entry_attr_get_charray_ext(e, CONFIG_CHANGELOG_INCLUDE_SUFFIX, &num_vals);
  339. if(values){
  340. for (i = 0;i < num_vals; i++){
  341. /* Validate the syntax before we create our DN array */
  342. if(slapi_dn_syntax_check(pb, values[i], 1)){
  343. /* invalid dn syntax */
  344. slapi_log_error(SLAPI_LOG_FATAL, RETROCL_PLUGIN_NAME,
  345. "Invalid DN (%s) for include suffix.\n", values[i] );
  346. slapi_ch_array_free(values);
  347. return -1;
  348. }
  349. }
  350. /* Now create our SDN array */
  351. retrocl_includes = (Slapi_DN **)slapi_ch_calloc(sizeof(Slapi_DN *),num_vals+1);
  352. for (i = 0;i < num_vals; i++){
  353. retrocl_includes[i] = slapi_sdn_new_dn_byval(values[i]);
  354. }
  355. slapi_ch_array_free(values);
  356. }
  357. if(retrocl_includes && retrocl_excludes){
  358. /*
  359. * Make sure we haven't mixed the same suffix, and there are no
  360. * conflicts between the includes and excludes
  361. */
  362. int i = 0;
  363. while(retrocl_includes[i]){
  364. int x = 0;
  365. while(retrocl_excludes[x]){
  366. if(slapi_sdn_compare(retrocl_includes[i], retrocl_excludes[x] ) == 0){
  367. /* we have a conflict */
  368. slapi_log_error(SLAPI_LOG_FATAL, RETROCL_PLUGIN_NAME,
  369. "include suffix (%s) is also listed in exclude suffix list\n",
  370. slapi_sdn_get_dn(retrocl_includes[i]));
  371. return -1;
  372. }
  373. x++;
  374. }
  375. i++;
  376. }
  377. /* Check for parent/child conflicts */
  378. i = 0;
  379. while(retrocl_includes[i]){
  380. int x = 0;
  381. while(retrocl_excludes[x]){
  382. if(slapi_sdn_issuffix(retrocl_includes[i], retrocl_excludes[x])){
  383. /* we have a conflict */
  384. slapi_log_error(SLAPI_LOG_FATAL, RETROCL_PLUGIN_NAME,
  385. "include suffix (%s) is a child of the exclude suffix(%s)\n",
  386. slapi_sdn_get_dn(retrocl_includes[i]),
  387. slapi_sdn_get_dn(retrocl_excludes[i]));
  388. return -1;
  389. }
  390. x++;
  391. }
  392. i++;
  393. }
  394. }
  395. values = slapi_entry_attr_get_charray(e, "nsslapd-attribute");
  396. if (values != NULL) {
  397. int n = 0;
  398. int i = 0;
  399. slapi_log_error(SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME, "nsslapd-attribute:\n");
  400. for (n=0; values && values[n]; n++) {
  401. slapi_log_error(SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME, " - %s\n", values[n]);
  402. }
  403. retrocl_nattributes = n;
  404. retrocl_attributes = (char **)slapi_ch_calloc(n, sizeof(char *));
  405. retrocl_aliases = (char **)slapi_ch_calloc(n, sizeof(char *));
  406. slapi_log_error(SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME, "Attributes:\n");
  407. for (i=0; i<n; i++) {
  408. char *value = values[i];
  409. size_t length = strlen(value);
  410. char *pos = strchr(value, ':');
  411. if (pos == NULL) {
  412. retrocl_attributes[i] = slapi_ch_strdup(value);
  413. retrocl_aliases[i] = NULL;
  414. slapi_log_error(SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME, " - %s\n",
  415. retrocl_attributes[i]);
  416. } else {
  417. retrocl_attributes[i] = slapi_ch_malloc(pos-value+1);
  418. strncpy(retrocl_attributes[i], value, pos-value);
  419. retrocl_attributes[i][pos-value] = '\0';
  420. retrocl_aliases[i] = slapi_ch_malloc(value+length-pos);
  421. strcpy(retrocl_aliases[i], pos+1);
  422. slapi_log_error(SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME, " - %s [%s]\n",
  423. retrocl_attributes[i], retrocl_aliases[i]);
  424. }
  425. }
  426. slapi_ch_array_free(values);
  427. }
  428. retrocl_log_deleted = 0;
  429. values = slapi_entry_attr_get_charray(e, "nsslapd-log-deleted");
  430. if (values != NULL) {
  431. if (values[1] != NULL) {
  432. slapi_log_error(SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME,
  433. "Multiple values specified for attribute: nsslapd-log-deleted\n");
  434. } else if ( 0 == strcasecmp(values[0], "on")) {
  435. retrocl_log_deleted = 1;
  436. } else if (strcasecmp(values[0], "off")) {
  437. slapi_log_error(SLAPI_LOG_PLUGIN, RETROCL_PLUGIN_NAME,
  438. "Invalid value (%s) specified for attribute: nsslapd-log-deleted\n", values[0]);
  439. }
  440. slapi_ch_array_free(values);
  441. }
  442. return 0;
  443. }
  444. /*
  445. * Check if an entry is in the configured scope.
  446. * Return 1 if entry is in the scope, or 0 otherwise.
  447. * For MODRDN the caller should check both the preop
  448. * and postop entries. If we are moving out of, or
  449. * into scope, we should record it.
  450. */
  451. int
  452. retrocl_entry_in_scope(Slapi_Entry *e)
  453. {
  454. Slapi_DN *sdn = slapi_entry_get_sdn(e);
  455. if (e == NULL){
  456. return 1;
  457. }
  458. if (retrocl_excludes){
  459. int i = 0;
  460. /* check the excludes */
  461. while(retrocl_excludes[i]){
  462. if (slapi_sdn_issuffix(sdn, retrocl_excludes[i])){
  463. return 0;
  464. }
  465. i++;
  466. }
  467. }
  468. if (retrocl_includes){
  469. int i = 0;
  470. /* check the excludes */
  471. while(retrocl_includes[i]){
  472. if (slapi_sdn_issuffix(sdn, retrocl_includes[i])){
  473. return 1;
  474. }
  475. i++;
  476. }
  477. return 0;
  478. }
  479. return 1;
  480. }
  481. /*
  482. * Function: retrocl_stop
  483. *
  484. * Returns: 0
  485. *
  486. * Arguments: Pb
  487. *
  488. * Description: called when the server is shutting down
  489. *
  490. */
  491. static int retrocl_stop (Slapi_PBlock *pb)
  492. {
  493. int rc = 0;
  494. int i = 0;
  495. slapi_ch_array_free(retrocl_attributes);
  496. retrocl_attributes = NULL;
  497. slapi_ch_array_free(retrocl_aliases);
  498. retrocl_aliases = NULL;
  499. while(retrocl_excludes && retrocl_excludes[i]){
  500. slapi_sdn_free(&retrocl_excludes[i]);
  501. i++;
  502. }
  503. slapi_ch_free((void**)&retrocl_excludes);
  504. i = 0;
  505. while(retrocl_includes && retrocl_includes[i]){
  506. slapi_sdn_free(&retrocl_includes[i]);
  507. i++;
  508. }
  509. slapi_ch_free((void**)&retrocl_includes);
  510. retrocl_stop_trimming();
  511. retrocl_be_changelog = NULL;
  512. retrocl_forget_changenumbers();
  513. PR_DestroyLock(retrocl_internal_lock);
  514. retrocl_internal_lock = NULL;
  515. slapi_destroy_rwlock(retrocl_cn_lock);
  516. retrocl_cn_lock = NULL;
  517. legacy_initialised = 0;
  518. slapi_config_remove_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, "",
  519. LDAP_SCOPE_BASE,"(objectclass=*)", retrocl_rootdse_search);
  520. return rc;
  521. }
  522. /*
  523. * Function: retrocl_plugin_init
  524. *
  525. * Returns: 0 on successs
  526. *
  527. * Arguments: Pb
  528. *
  529. * Description: main entry point for retrocl
  530. *
  531. */
  532. int
  533. retrocl_plugin_init(Slapi_PBlock *pb)
  534. {
  535. int rc = 0;
  536. int precedence = 0;
  537. void *identity = NULL;
  538. Slapi_Entry *plugin_entry = NULL;
  539. int is_betxn = 0;
  540. const char *plugintype = "postoperation";
  541. slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &identity);
  542. PR_ASSERT (identity);
  543. g_plg_identity[PLUGIN_RETROCL] = identity;
  544. slapi_pblock_get( pb, SLAPI_PLUGIN_PRECEDENCE, &precedence );
  545. if ((slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry) == 0) &&
  546. plugin_entry) {
  547. is_betxn = slapi_entry_attr_get_bool(plugin_entry, "nsslapd-pluginbetxn");
  548. }
  549. if (!legacy_initialised) {
  550. rc= slapi_pblock_set( pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01 );
  551. rc= slapi_pblock_set( pb, SLAPI_PLUGIN_DESCRIPTION, (void *)&retrocldesc );
  552. rc= slapi_pblock_set( pb, SLAPI_PLUGIN_START_FN, (void *) retrocl_start );
  553. rc= slapi_pblock_set( pb, SLAPI_PLUGIN_CLOSE_FN, (void *) retrocl_stop );
  554. if (is_betxn) {
  555. plugintype = "betxnpostoperation";
  556. }
  557. rc= slapi_register_plugin_ext(plugintype, 1 /* Enabled */, "retrocl_postop_init", retrocl_postop_init, "Retrocl postoperation plugin", NULL, identity, precedence);
  558. if (!is_betxn) {
  559. rc= slapi_register_plugin_ext("internalpostoperation", 1 /* Enabled */, "retrocl_internalpostop_init", retrocl_internalpostop_init, "Retrocl internal postoperation plugin", NULL, identity, precedence);
  560. }
  561. retrocl_cn_lock = slapi_new_rwlock();
  562. if(retrocl_cn_lock == NULL) return -1;
  563. retrocl_internal_lock = PR_NewLock();
  564. if (retrocl_internal_lock == NULL) return -1;
  565. }
  566. legacy_initialised = 1;
  567. return rc;
  568. }