windows_private.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. /* windows_private.c */
  39. #include "repl.h"
  40. #include "repl5.h"
  41. #include "slap.h"
  42. #include "slapi-plugin.h"
  43. #include "windowsrepl.h"
  44. struct windowsprivate {
  45. Slapi_DN *windows_subtree; /* DN of synchronized subtree (on the windows side) */
  46. Slapi_DN *directory_subtree; /* DN of synchronized subtree on directory side */
  47. /* this simplifies the mapping as it's simply
  48. from the former to the latter container, or
  49. vice versa */
  50. int dirsync_flags;
  51. int dirsync_maxattributecount;
  52. char *dirsync_cookie;
  53. int dirsync_cookie_len;
  54. PRBool dirsync_cookie_has_more;
  55. PRBool create_users_from_dirsync;
  56. PRBool create_groups_from_dirsync;
  57. char *windows_domain;
  58. int isnt4;
  59. };
  60. static int
  61. true_value_from_string(char *val)
  62. {
  63. if (strcasecmp (val, "on") == 0 || strcasecmp (val, "yes") == 0 ||
  64. strcasecmp (val, "true") == 0 || strcasecmp (val, "1") == 0)
  65. {
  66. return 1;
  67. } else
  68. {
  69. return 0;
  70. }
  71. }
  72. static int
  73. windows_parse_config_entry(Repl_Agmt *ra, const char *type, Slapi_Entry *e)
  74. {
  75. char *tmpstr = NULL;
  76. int retval = 0;
  77. if (type == NULL || slapi_attr_types_equivalent(type,type_nsds7WindowsReplicaArea))
  78. {
  79. tmpstr = slapi_entry_attr_get_charptr(e, type_nsds7WindowsReplicaArea);
  80. if (NULL != tmpstr)
  81. {
  82. windows_private_set_windows_subtree(ra, slapi_sdn_new_dn_passin(tmpstr) );
  83. }
  84. retval = 1;
  85. slapi_ch_free((void**)&tmpstr);
  86. }
  87. if (type == NULL || slapi_attr_types_equivalent(type,type_nsds7DirectoryReplicaArea))
  88. {
  89. tmpstr = slapi_entry_attr_get_charptr(e, type_nsds7DirectoryReplicaArea);
  90. if (NULL != tmpstr)
  91. {
  92. windows_private_set_directory_subtree(ra, slapi_sdn_new_dn_passin(tmpstr) );
  93. }
  94. retval = 1;
  95. slapi_ch_free((void**)&tmpstr);
  96. }
  97. if (type == NULL || slapi_attr_types_equivalent(type,type_nsds7CreateNewUsers))
  98. {
  99. tmpstr = slapi_entry_attr_get_charptr(e, type_nsds7CreateNewUsers);
  100. if (NULL != tmpstr && true_value_from_string(tmpstr))
  101. {
  102. windows_private_set_create_users(ra, PR_TRUE);
  103. }
  104. else
  105. {
  106. windows_private_set_create_users(ra, PR_FALSE);
  107. }
  108. retval = 1;
  109. slapi_ch_free((void**)&tmpstr);
  110. }
  111. if (type == NULL || slapi_attr_types_equivalent(type,type_nsds7CreateNewGroups))
  112. {
  113. tmpstr = slapi_entry_attr_get_charptr(e, type_nsds7CreateNewGroups);
  114. if (NULL != tmpstr && true_value_from_string(tmpstr))
  115. {
  116. windows_private_set_create_groups(ra, PR_TRUE);
  117. }
  118. else
  119. {
  120. windows_private_set_create_groups(ra, PR_FALSE);
  121. }
  122. retval = 1;
  123. slapi_ch_free((void**)&tmpstr);
  124. }
  125. if (type == NULL || slapi_attr_types_equivalent(type,type_nsds7WindowsDomain))
  126. {
  127. tmpstr = slapi_entry_attr_get_charptr(e, type_nsds7WindowsDomain);
  128. if (NULL != tmpstr)
  129. {
  130. windows_private_set_windows_domain(ra,tmpstr);
  131. }
  132. /* No need to free tmpstr because it was aliased by the call above */
  133. tmpstr = NULL;
  134. retval = 1;
  135. }
  136. return retval;
  137. }
  138. /* Returns non-zero if the modify was ok, zero if not */
  139. int
  140. windows_handle_modify_agreement(Repl_Agmt *ra, const char *type, Slapi_Entry *e)
  141. {
  142. /* Is this a Windows agreement ? */
  143. if (get_agmt_agreement_type(ra) == REPLICA_TYPE_WINDOWS)
  144. {
  145. return windows_parse_config_entry(ra,type,e);
  146. } else
  147. {
  148. return 0;
  149. }
  150. }
  151. void
  152. windows_init_agreement_from_entry(Repl_Agmt *ra, Slapi_Entry *e)
  153. {
  154. agmt_set_priv(ra,windows_private_new());
  155. windows_parse_config_entry(ra,NULL,e);
  156. }
  157. const char* windows_private_get_purl(const Repl_Agmt *ra)
  158. {
  159. const char* windows_purl;
  160. char *hostname;
  161. hostname = agmt_get_hostname(ra);
  162. windows_purl = slapi_ch_smprintf("ldap://%s:%d", hostname, agmt_get_port(ra));
  163. slapi_ch_free_string(&hostname);
  164. return windows_purl;
  165. }
  166. Dirsync_Private* windows_private_new()
  167. {
  168. Dirsync_Private *dp;
  169. LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_new\n", 0, 0, 0 );
  170. dp = (Dirsync_Private *)slapi_ch_calloc(sizeof(Dirsync_Private),1);
  171. dp->dirsync_maxattributecount = -1;
  172. LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_new\n", 0, 0, 0 );
  173. return dp;
  174. }
  175. void windows_agreement_delete(Repl_Agmt *ra)
  176. {
  177. Dirsync_Private *dp = (Dirsync_Private *) agmt_get_priv(ra);
  178. LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_delete\n", 0, 0, 0 );
  179. PR_ASSERT(dp != NULL);
  180. /* DBDB: need to free payoad here */
  181. slapi_ch_free((void **)dp);
  182. LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_delete\n", 0, 0, 0 );
  183. }
  184. int windows_private_get_isnt4(const Repl_Agmt *ra)
  185. {
  186. Dirsync_Private *dp;
  187. LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_get_isnt4\n", 0, 0, 0 );
  188. PR_ASSERT(ra);
  189. dp = (Dirsync_Private *) agmt_get_priv(ra);
  190. PR_ASSERT (dp);
  191. LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_get_isnt4\n", 0, 0, 0 );
  192. return dp->isnt4;
  193. }
  194. void windows_private_set_isnt4(const Repl_Agmt *ra, int isit)
  195. {
  196. Dirsync_Private *dp;
  197. LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_set_isnt4\n", 0, 0, 0 );
  198. PR_ASSERT(ra);
  199. dp = (Dirsync_Private *) agmt_get_priv(ra);
  200. PR_ASSERT (dp);
  201. dp->isnt4 = isit;
  202. LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_set_isnt4\n", 0, 0, 0 );
  203. }
  204. /* Returns a copy of the Slapi_DN pointer, no need to free it */
  205. const Slapi_DN* windows_private_get_windows_subtree (const Repl_Agmt *ra)
  206. {
  207. Dirsync_Private *dp;
  208. LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_get_windows_subtree\n", 0, 0, 0 );
  209. PR_ASSERT(ra);
  210. dp = (Dirsync_Private *) agmt_get_priv(ra);
  211. PR_ASSERT (dp);
  212. LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_get_windows_subtree\n", 0, 0, 0 );
  213. return dp->windows_subtree;
  214. }
  215. const char *
  216. windows_private_get_windows_domain(const Repl_Agmt *ra)
  217. {
  218. Dirsync_Private *dp;
  219. LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_get_windows_domain\n", 0, 0, 0 );
  220. PR_ASSERT(ra);
  221. dp = (Dirsync_Private *) agmt_get_priv(ra);
  222. PR_ASSERT (dp);
  223. LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_get_windows_domain\n", 0, 0, 0 );
  224. return dp->windows_domain;
  225. }
  226. static void
  227. windows_private_set_windows_domain(const Repl_Agmt *ra, char *domain)
  228. {
  229. Dirsync_Private *dp;
  230. LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_set_windows_domain\n", 0, 0, 0 );
  231. PR_ASSERT(ra);
  232. dp = (Dirsync_Private *) agmt_get_priv(ra);
  233. PR_ASSERT (dp);
  234. dp->windows_domain = domain;
  235. LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_set_windows_domain\n", 0, 0, 0 );
  236. }
  237. /* Returns a copy of the Slapi_DN pointer, no need to free it */
  238. const Slapi_DN* windows_private_get_directory_subtree (const Repl_Agmt *ra)
  239. {
  240. Dirsync_Private *dp;
  241. LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_get_directory_replarea\n", 0, 0, 0 );
  242. PR_ASSERT(ra);
  243. dp = (Dirsync_Private *) agmt_get_priv(ra);
  244. PR_ASSERT (dp);
  245. LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_get_directory_replarea\n", 0, 0, 0 );
  246. return dp->directory_subtree;
  247. }
  248. /* Takes a copy of the sdn passed in */
  249. void windows_private_set_windows_subtree (const Repl_Agmt *ra,const Slapi_DN* sdn )
  250. {
  251. Dirsync_Private *dp;
  252. LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_set_windows_replarea\n", 0, 0, 0 );
  253. PR_ASSERT(ra);
  254. PR_ASSERT(sdn);
  255. dp = (Dirsync_Private *) agmt_get_priv(ra);
  256. PR_ASSERT (dp);
  257. dp->windows_subtree = slapi_sdn_dup(sdn);
  258. LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_set_windows_replarea\n", 0, 0, 0 );
  259. }
  260. /* Takes a copy of the sdn passed in */
  261. void windows_private_set_directory_subtree (const Repl_Agmt *ra,const Slapi_DN* sdn )
  262. {
  263. Dirsync_Private *dp;
  264. LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_set_directory_replarea\n", 0, 0, 0 );
  265. PR_ASSERT(ra);
  266. PR_ASSERT(sdn);
  267. dp = (Dirsync_Private *) agmt_get_priv(ra);
  268. PR_ASSERT (dp);
  269. dp->directory_subtree = slapi_sdn_dup(sdn);
  270. LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_set_directory_replarea\n", 0, 0, 0 );
  271. }
  272. PRBool windows_private_create_users(const Repl_Agmt *ra)
  273. {
  274. Dirsync_Private *dp;
  275. LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_create_users\n", 0, 0, 0 );
  276. PR_ASSERT(ra);
  277. dp = (Dirsync_Private *) agmt_get_priv(ra);
  278. PR_ASSERT (dp);
  279. LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_create_users\n", 0, 0, 0 );
  280. return dp->create_users_from_dirsync;
  281. }
  282. void windows_private_set_create_users(const Repl_Agmt *ra, PRBool value)
  283. {
  284. Dirsync_Private *dp;
  285. LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_set_create_users\n", 0, 0, 0 );
  286. PR_ASSERT(ra);
  287. dp = (Dirsync_Private *) agmt_get_priv(ra);
  288. PR_ASSERT (dp);
  289. dp->create_users_from_dirsync = value;
  290. LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_set_create_users\n", 0, 0, 0 );
  291. }
  292. PRBool windows_private_create_groups(const Repl_Agmt *ra)
  293. {
  294. Dirsync_Private *dp;
  295. LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_create_groups\n", 0, 0, 0 );
  296. PR_ASSERT(ra);
  297. dp = (Dirsync_Private *) agmt_get_priv(ra);
  298. PR_ASSERT (dp);
  299. LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_create_groups\n", 0, 0, 0 );
  300. return dp->create_groups_from_dirsync;
  301. }
  302. void windows_private_set_create_groups(const Repl_Agmt *ra, PRBool value)
  303. {
  304. Dirsync_Private *dp;
  305. LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_set_create_groups\n", 0, 0, 0 );
  306. PR_ASSERT(ra);
  307. dp = (Dirsync_Private *) agmt_get_priv(ra);
  308. PR_ASSERT (dp);
  309. dp->create_groups_from_dirsync = value;
  310. LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_set_create_groups\n", 0, 0, 0 );
  311. }
  312. /*
  313. This function returns the current Dirsync_Private that's inside
  314. Repl_Agmt ra as a ldap control.
  315. */
  316. LDAPControl* windows_private_dirsync_control(const Repl_Agmt *ra)
  317. {
  318. LDAPControl *control = NULL;
  319. BerElement *ber;
  320. Dirsync_Private *dp;
  321. LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_dirsync_control\n", 0, 0, 0 );
  322. PR_ASSERT(ra);
  323. dp = (Dirsync_Private *) agmt_get_priv(ra);
  324. PR_ASSERT (dp);
  325. ber = ber_alloc();
  326. ber_printf( ber, "{iio}", dp->dirsync_flags, dp->dirsync_maxattributecount, dp->dirsync_cookie, dp->dirsync_cookie_len );
  327. slapi_build_control( REPL_DIRSYNC_CONTROL_OID, ber, PR_TRUE, &control);
  328. ber_free(ber,1);
  329. LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_dirsync_control\n", 0, 0, 0 );
  330. return control;
  331. }
  332. /*
  333. This function scans the array of controls and updates the Repl_Agmt's
  334. Dirsync_Private if the dirsync control is found.
  335. */
  336. void windows_private_update_dirsync_control(const Repl_Agmt *ra,LDAPControl **controls )
  337. {
  338. Dirsync_Private *dp;
  339. int foundDirsyncControl;
  340. int i;
  341. LDAPControl *dirsync;
  342. BerElement *ber;
  343. ber_int_t hasMoreData;
  344. ber_int_t maxAttributeCount;
  345. BerValue *serverCookie;
  346. int return_value = LDAP_SUCCESS;
  347. LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_update_dirsync_control\n", 0, 0, 0 );
  348. PR_ASSERT(ra);
  349. dp = (Dirsync_Private *) agmt_get_priv(ra);
  350. PR_ASSERT (dp);
  351. if (NULL != controls )
  352. {
  353. foundDirsyncControl = 0;
  354. for ( i = 0; (( controls[i] != NULL ) && ( !foundDirsyncControl )); i++ ) {
  355. foundDirsyncControl = !strcmp( controls[i]->ldctl_oid, REPL_DIRSYNC_CONTROL_OID );
  356. }
  357. if ( !foundDirsyncControl )
  358. {
  359. return_value = LDAP_CONTROL_NOT_FOUND;
  360. goto choke;
  361. }
  362. else
  363. {
  364. dirsync = slapi_dup_control( controls[i-1]);
  365. }
  366. ber = ber_init( &dirsync->ldctl_value ) ;
  367. if (ber_scanf( ber, "{iiO}", &hasMoreData, &maxAttributeCount, &serverCookie) == LBER_ERROR)
  368. {
  369. return_value = LDAP_CONTROL_NOT_FOUND;
  370. goto choke;
  371. }
  372. slapi_ch_free_string(&dp->dirsync_cookie);
  373. dp->dirsync_cookie = ( char* ) slapi_ch_malloc(serverCookie->bv_len + 1);
  374. memcpy(dp->dirsync_cookie, serverCookie->bv_val, serverCookie->bv_len);
  375. dp->dirsync_cookie_len = (int) serverCookie->bv_len; /* XXX shouldn't cast? */
  376. /* dp->dirsync_maxattributecount = maxAttributeCount; We don't need to keep this */
  377. dp->dirsync_cookie_has_more = hasMoreData;
  378. choke:
  379. ber_bvfree(serverCookie);
  380. ber_free(ber,1);
  381. }
  382. else
  383. {
  384. return_value = LDAP_CONTROL_NOT_FOUND;
  385. }
  386. LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_update_dirsync_control\n", 0, 0, 0 );
  387. /* return return_value; */
  388. }
  389. PRBool windows_private_dirsync_has_more(const Repl_Agmt *ra)
  390. {
  391. Dirsync_Private *dp;
  392. LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_dirsync_has_more\n", 0, 0, 0 );
  393. PR_ASSERT(ra);
  394. dp = (Dirsync_Private *) agmt_get_priv(ra);
  395. PR_ASSERT (dp);
  396. LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_dirsync_has_more\n", 0, 0, 0 );
  397. return dp->dirsync_cookie_has_more;
  398. }
  399. void windows_private_null_dirsync_cookie(const Repl_Agmt *ra)
  400. {
  401. Dirsync_Private *dp;
  402. LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_null_dirsync_control\n", 0, 0, 0 );
  403. dp = (Dirsync_Private *) agmt_get_priv(ra);
  404. PR_ASSERT (dp);
  405. dp->dirsync_cookie_len = 0;
  406. slapi_ch_free_string(&dp->dirsync_cookie);
  407. dp->dirsync_cookie = NULL;
  408. LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_null_dirsync_control\n", 0, 0, 0 );
  409. }
  410. static
  411. Slapi_Mods *windows_private_get_cookie_mod(Dirsync_Private *dp, int modtype)
  412. {
  413. Slapi_Mods *smods = NULL;
  414. smods = slapi_mods_new();
  415. slapi_mods_add( smods, modtype,
  416. "nsds7DirsyncCookie", dp->dirsync_cookie_len , dp->dirsync_cookie);
  417. return smods;
  418. }
  419. /* writes the current cookie into dse.ldif under the replication agreement entry
  420. returns: ldap result code of the operation. */
  421. int
  422. windows_private_save_dirsync_cookie(const Repl_Agmt *ra)
  423. {
  424. Dirsync_Private *dp = NULL;
  425. Slapi_PBlock *pb = NULL;
  426. const char* dn = NULL;
  427. Slapi_DN* sdn = NULL;
  428. int rc = 0;
  429. Slapi_Mods *mods = NULL;
  430. LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_save_dirsync_cookie\n", 0, 0, 0 );
  431. PR_ASSERT(ra);
  432. dp = (Dirsync_Private *) agmt_get_priv(ra);
  433. PR_ASSERT (dp);
  434. pb = slapi_pblock_new ();
  435. mods = windows_private_get_cookie_mod(dp, LDAP_MOD_REPLACE);
  436. sdn = slapi_sdn_dup( agmt_get_dn_byref(ra) );
  437. dn = slapi_sdn_get_dn(sdn);
  438. slapi_modify_internal_set_pb (pb, dn, slapi_mods_get_ldapmods_byref(mods), NULL, NULL,
  439. repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0);
  440. slapi_modify_internal_pb (pb);
  441. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
  442. if (rc == LDAP_NO_SUCH_ATTRIBUTE)
  443. { /* try again, but as an add instead */
  444. mods = windows_private_get_cookie_mod(dp, LDAP_MOD_ADD);
  445. slapi_modify_internal_set_pb (pb, dn, slapi_mods_get_ldapmods_byref(mods), NULL, NULL,
  446. repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION), 0);
  447. slapi_modify_internal_pb (pb);
  448. slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
  449. }
  450. slapi_pblock_destroy (pb);
  451. slapi_mods_free(&mods);
  452. slapi_sdn_free(&sdn);
  453. LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_save_dirsync_cookie\n", 0, 0, 0 );
  454. return rc;
  455. }
  456. /* reads the cookie in dse.ldif to the replication agreement entry
  457. returns: ldap result code of ldap operation, or
  458. LDAP_NO_SUCH_ATTRIBUTE. (this is the equilivent of a null cookie) */
  459. int windows_private_load_dirsync_cookie(const Repl_Agmt *ra)
  460. {
  461. Dirsync_Private *dp = NULL;
  462. Slapi_PBlock *pb = NULL;
  463. Slapi_DN* sdn = NULL;
  464. int rc = 0;
  465. Slapi_Entry *entry = NULL;
  466. Slapi_Attr *attr = NULL;
  467. LDAPDebug( LDAP_DEBUG_TRACE, "=> windows_private_load_dirsync_cookie\n", 0, 0, 0 );
  468. PR_ASSERT(ra);
  469. dp = (Dirsync_Private *) agmt_get_priv(ra);
  470. PR_ASSERT (dp);
  471. pb = slapi_pblock_new ();
  472. sdn = slapi_sdn_dup( agmt_get_dn_byref(ra) );
  473. rc = slapi_search_internal_get_entry(sdn, NULL, &entry,
  474. repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION));
  475. if (rc == 0)
  476. {
  477. rc= slapi_entry_attr_find( entry, type_nsds7DirsyncCookie, &attr );
  478. if (attr)
  479. {
  480. struct berval **vals;
  481. rc = slapi_attr_get_bervals_copy(attr, &vals );
  482. if (vals)
  483. {
  484. dp->dirsync_cookie_len = (int) (vals[0])->bv_len;
  485. slapi_ch_free_string(&dp->dirsync_cookie);
  486. dp->dirsync_cookie = ( char* ) slapi_ch_malloc(dp->dirsync_cookie_len + 1);
  487. memcpy(dp->dirsync_cookie,(vals[0]->bv_val), (vals[0])->bv_len+1);
  488. }
  489. ber_bvecfree(vals);
  490. /* we do not free attr */
  491. }
  492. else
  493. {
  494. rc = LDAP_NO_SUCH_ATTRIBUTE;
  495. }
  496. }
  497. if (entry)
  498. {
  499. slapi_entry_free(entry);
  500. }
  501. slapi_sdn_free( &sdn);
  502. slapi_pblock_destroy (pb);
  503. LDAPDebug( LDAP_DEBUG_TRACE, "<= windows_private_load_dirsync_cookie\n", 0, 0, 0 );
  504. return rc;
  505. }