operation.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  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. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. /* operation.c - routines to deal with pending ldap operations */
  42. #include <stdio.h>
  43. #include <string.h>
  44. #include <sys/types.h>
  45. #ifndef _WIN32
  46. #include <sys/socket.h>
  47. #endif
  48. #include "slap.h"
  49. int
  50. slapi_op_abandoned( Slapi_PBlock *pb )
  51. {
  52. int op_status;
  53. if (pb && pb->pb_op) {
  54. op_status = pb->pb_op->o_status;
  55. return( op_status == SLAPI_OP_STATUS_ABANDONED );
  56. }
  57. return 0;
  58. }
  59. void
  60. operation_out_of_disk_space()
  61. {
  62. LDAPDebug(LDAP_DEBUG_ANY, "*** DISK FULL ***\n", 0, 0, 0);
  63. LDAPDebug(LDAP_DEBUG_ANY, "Attempting to shut down gracefully.\n", 0, 0, 0);
  64. g_set_shutdown( SLAPI_SHUTDOWN_DISKFULL );
  65. }
  66. /* Setting the flags on the operation allows more control to the plugin
  67. * to disable and enable checks
  68. * Flags that we support for setting in the operation from the plugin are
  69. * SLAPI_OP_FLAG_NO_ACCESS_CHECK - do not check for access control
  70. * This function can be extended to support other flag setting as well
  71. */
  72. void slapi_operation_set_flag(Slapi_Operation *op, unsigned long flag)
  73. {
  74. operation_set_flag(op, flag);
  75. }
  76. void slapi_operation_clear_flag(Slapi_Operation *op, unsigned long flag)
  77. {
  78. operation_clear_flag(op, flag);
  79. }
  80. int slapi_operation_is_flag_set(Slapi_Operation *op, unsigned long flag)
  81. {
  82. return operation_is_flag_set(op, flag);
  83. }
  84. static int operation_type = -1; /* The type number assigned by the Factory for 'Operation' */
  85. int
  86. get_operation_object_type()
  87. {
  88. if(operation_type==-1)
  89. {
  90. /* The factory is given the name of the object type, in
  91. * return for a type handle. Whenever the object is created
  92. * or destroyed the factory is called with the handle so
  93. * that it may call the constructors or destructors registered
  94. * with it.
  95. */
  96. operation_type= factory_register_type(SLAPI_EXT_OPERATION,offsetof(Operation,o_extension));
  97. }
  98. return operation_type;
  99. }
  100. #if defined(USE_OPENLDAP)
  101. /* openldap doesn't have anything like this, nor does it have
  102. a way to portably and without cheating discover the
  103. sizeof BerElement - see lber_pvt.h for the trick used
  104. for BerElementBuffer
  105. so we just allocate everything separately
  106. If we wanted to get fancy, we could use LBER_OPT_MEMORY_FNS
  107. to override the ber malloc, realloc, etc. and use
  108. LBER_OPT_BER_MEMCTX to provide callback data for use
  109. with those functions
  110. */
  111. static void*
  112. ber_special_alloc(size_t size, BerElement **ppBer)
  113. {
  114. void *mem = NULL;
  115. /* starts out with a null buffer - will grow as needed */
  116. *ppBer = ber_alloc_t(0);
  117. /* Make sure mem size requested is aligned */
  118. if (0 != ( size & 0x03 )) {
  119. size += (sizeof(ber_int_t) - (size & 0x03));
  120. }
  121. mem = slapi_ch_malloc(size);
  122. return mem;
  123. }
  124. static void
  125. ber_special_free(void* buf, BerElement *ber)
  126. {
  127. ber_free(ber, 1);
  128. slapi_ch_free(&buf);
  129. }
  130. #endif
  131. /*
  132. * Allocate a new Slapi_Operation.
  133. * The flag parameter indicates whether the the operation is
  134. * external (from an LDAP Client), or internal (from a plugin).
  135. */
  136. Slapi_Operation *
  137. operation_new(int flags)
  138. {
  139. /* To improve performance, we allocate the Operation, BerElement and
  140. * ber buffer in one block, instead of a separate malloc() for each.
  141. * Subsequently, ber_special_free() frees them all; we're careful
  142. * not to free the Operation separately, and the ber software knows
  143. * not to free the buffer separately.
  144. */
  145. BerElement *ber = NULL;
  146. Slapi_Operation *o;
  147. if(flags & OP_FLAG_INTERNAL)
  148. {
  149. o = (Slapi_Operation *) slapi_ch_malloc(sizeof(Slapi_Operation));
  150. }
  151. else
  152. {
  153. o= (Slapi_Operation *) ber_special_alloc( sizeof(Slapi_Operation), &ber );
  154. }
  155. if (NULL != o)
  156. {
  157. memset(o,0,sizeof(Slapi_Operation));
  158. o->o_ber = ber;
  159. o->o_msgid = -1;
  160. o->o_tag = LBER_DEFAULT;
  161. o->o_status = SLAPI_OP_STATUS_PROCESSING;
  162. slapi_sdn_init(&(o->o_sdn));
  163. o->o_authtype = NULL;
  164. o->o_isroot = 0;
  165. o->o_time = current_time();
  166. o->o_opid = 0;
  167. o->o_connid = 0;
  168. o->o_next = NULL;
  169. o->o_flags= flags;
  170. if ( config_get_accesslog_level() & LDAP_DEBUG_TIMING ) {
  171. o->o_interval = PR_IntervalNow();
  172. } else {
  173. o->o_interval = (PRIntervalTime)0;
  174. }
  175. }
  176. return o;
  177. }
  178. void
  179. operation_free( Slapi_Operation **op, Connection *conn )
  180. {
  181. if(op!=NULL && *op!=NULL)
  182. {
  183. /* Call the plugin extension destructors */
  184. factory_destroy_extension(get_operation_object_type(),*op,conn,&((*op)->o_extension));
  185. slapi_sdn_done(&(*op)->o_sdn);
  186. slapi_sdn_free(&(*op)->o_target_spec);
  187. slapi_ch_free_string( &(*op)->o_authtype );
  188. if ( (*op)->o_searchattrs != NULL ) {
  189. cool_charray_free( (*op)->o_searchattrs );
  190. }
  191. if ( NULL != (*op)->o_params.request_controls ) {
  192. ldap_controls_free( (*op)->o_params.request_controls );
  193. }
  194. if ( NULL != (*op)->o_results.result_controls ) {
  195. ldap_controls_free( (*op)->o_results.result_controls );
  196. }
  197. slapi_ch_free_string(&(*op)->o_results.result_matched);
  198. if(operation_is_flag_set(*op, OP_FLAG_INTERNAL))
  199. {
  200. slapi_ch_free((void**)op);
  201. }
  202. else
  203. {
  204. ber_special_free( *op , (*op)->o_ber);
  205. }
  206. /* counters_to_errors_log("after operation"); */
  207. }
  208. }
  209. void
  210. slapi_operation_set_csngen_handler ( Slapi_Operation *op, void *callback )
  211. {
  212. op->o_csngen_handler = (csngen_handler) callback;
  213. }
  214. void
  215. slapi_operation_set_replica_attr_handler ( Slapi_Operation *op, void *callback )
  216. {
  217. op->o_replica_attr_handler = (replica_attr_handler) callback;
  218. }
  219. int
  220. slapi_operation_get_replica_attr ( Slapi_PBlock *pb, Slapi_Operation *op, const char *type, void *value )
  221. {
  222. int rc = -1;
  223. if (op->o_replica_attr_handler)
  224. {
  225. rc = op->o_replica_attr_handler ( pb, type, value );
  226. }
  227. return rc;
  228. }
  229. CSN *
  230. operation_get_csn(Slapi_Operation *op)
  231. {
  232. return op->o_params.csn;
  233. }
  234. void
  235. operation_set_csn(Slapi_Operation *op,CSN *csn)
  236. {
  237. op->o_params.csn= csn;
  238. }
  239. unsigned long
  240. slapi_op_get_type(Slapi_Operation *op)
  241. {
  242. return op->o_params.operation_type;
  243. }
  244. char *
  245. slapi_op_type_to_string(unsigned long type)
  246. {
  247. switch (type)
  248. {
  249. case SLAPI_OPERATION_ADD:
  250. return "add";
  251. case SLAPI_OPERATION_DELETE:
  252. return "delete";
  253. case SLAPI_OPERATION_MODIFY:
  254. return "modify";
  255. case SLAPI_OPERATION_MODRDN:
  256. return "modrdn";
  257. case SLAPI_OPERATION_BIND:
  258. return "bind";
  259. case SLAPI_OPERATION_COMPARE:
  260. return "compare";
  261. case SLAPI_OPERATION_SEARCH:
  262. return "search";
  263. default:
  264. return "unknown operation type";
  265. }
  266. }
  267. /* DEPRECATED : USE FUNCTION ABOVE FOR NEW DVLPT */
  268. unsigned long
  269. operation_get_type(Slapi_Operation *op)
  270. {
  271. return op->o_params.operation_type;
  272. }
  273. void
  274. operation_set_type(Slapi_Operation *op, unsigned long type)
  275. {
  276. op->o_params.operation_type= type;
  277. }
  278. void
  279. operation_set_flag(Slapi_Operation *op, int flag)
  280. {
  281. op->o_flags|= flag;
  282. }
  283. void
  284. operation_clear_flag(Slapi_Operation *op, int flag)
  285. {
  286. op->o_flags &= ~flag;
  287. }
  288. int
  289. operation_is_flag_set(Slapi_Operation *op, int flag)
  290. {
  291. return op->o_flags & flag;
  292. }
  293. Slapi_DN*
  294. operation_get_target_spec (Slapi_Operation *op)
  295. {
  296. return op->o_target_spec;
  297. }
  298. void
  299. operation_set_target_spec (Slapi_Operation *op, const Slapi_DN *target_spec)
  300. {
  301. PR_ASSERT (op);
  302. PR_ASSERT (target_spec);
  303. op->o_target_spec = slapi_sdn_dup(target_spec);
  304. }
  305. void
  306. operation_set_target_spec_str (Slapi_Operation *op, const char *target_spec)
  307. {
  308. PR_ASSERT (op);
  309. op->o_target_spec = slapi_sdn_new_dn_byval (target_spec);
  310. }
  311. unsigned long operation_get_abandoned_op (const Slapi_Operation *op)
  312. {
  313. PR_ASSERT (op);
  314. return op->o_abandoned_op;
  315. }
  316. void operation_set_abandoned_op (Slapi_Operation *op, unsigned long abandoned_op)
  317. {
  318. PR_ASSERT (op);
  319. op->o_abandoned_op = abandoned_op;
  320. }
  321. /* slapi_operation_parameters manipulation functions */
  322. struct slapi_operation_parameters *operation_parameters_new()
  323. {
  324. return (slapi_operation_parameters *)slapi_ch_calloc (1, sizeof (slapi_operation_parameters));
  325. }
  326. static LDAPMod **
  327. copy_mods(LDAPMod **orig_mods)
  328. {
  329. LDAPMod **new_mods = NULL;
  330. LDAPMod *mod;
  331. Slapi_Mods smods_old;
  332. Slapi_Mods smods_new;
  333. slapi_mods_init_byref(&smods_old,orig_mods);
  334. slapi_mods_init_passin(&smods_new,new_mods);
  335. mod= slapi_mods_get_first_mod(&smods_old);
  336. while(mod!=NULL)
  337. {
  338. slapi_mods_add_modbvps(&smods_new,mod->mod_op,mod->mod_type,mod->mod_bvalues);
  339. mod= slapi_mods_get_next_mod(&smods_old);
  340. }
  341. new_mods= slapi_mods_get_ldapmods_passout(&smods_new);
  342. slapi_mods_done(&smods_old);
  343. slapi_mods_done(&smods_new);
  344. return new_mods;
  345. }
  346. struct slapi_operation_parameters *
  347. operation_parameters_dup(struct slapi_operation_parameters *sop)
  348. {
  349. struct slapi_operation_parameters *sop_new= (struct slapi_operation_parameters *)
  350. slapi_ch_malloc(sizeof(struct slapi_operation_parameters));
  351. memcpy(sop_new,sop,sizeof(struct slapi_operation_parameters));
  352. if(sop->target_address.dn!=NULL)
  353. {
  354. sop_new->target_address.dn= slapi_ch_strdup(sop->target_address.dn);
  355. }
  356. if(sop->target_address.uniqueid!=NULL)
  357. {
  358. sop_new->target_address.uniqueid= slapi_ch_strdup(sop->target_address.uniqueid);
  359. }
  360. sop_new->csn= csn_dup(sop->csn);
  361. switch(sop->operation_type)
  362. {
  363. case SLAPI_OPERATION_ADD:
  364. sop_new->p.p_add.target_entry= slapi_entry_dup(sop->p.p_add.target_entry);
  365. sop_new->p.p_add.parentuniqueid = slapi_ch_strdup(sop->p.p_add.parentuniqueid);
  366. break;
  367. case SLAPI_OPERATION_MODIFY:
  368. sop_new->p.p_modify.modify_mods= NULL;
  369. if (sop->p.p_modify.modify_mods!=NULL)
  370. {
  371. sop_new->p.p_modify.modify_mods = copy_mods(sop->p.p_modify.modify_mods);
  372. }
  373. break;
  374. case SLAPI_OPERATION_MODRDN:
  375. if(sop->p.p_modrdn.modrdn_newrdn!=NULL)
  376. {
  377. sop_new->p.p_modrdn.modrdn_newrdn= slapi_ch_strdup(sop->p.p_modrdn.modrdn_newrdn);
  378. }
  379. if(sop->p.p_modrdn.modrdn_newsuperior_address.dn!=NULL)
  380. {
  381. sop_new->p.p_modrdn.modrdn_newsuperior_address.dn =
  382. slapi_ch_strdup(sop->p.p_modrdn.modrdn_newsuperior_address.dn);
  383. }
  384. if(sop->p.p_modrdn.modrdn_newsuperior_address.uniqueid!=NULL)
  385. {
  386. sop_new->p.p_modrdn.modrdn_newsuperior_address.uniqueid =
  387. slapi_ch_strdup(sop->p.p_modrdn.modrdn_newsuperior_address.uniqueid);
  388. }
  389. sop_new->p.p_modrdn.modrdn_mods= NULL;
  390. if (sop->p.p_modrdn.modrdn_mods!=NULL)
  391. {
  392. sop_new->p.p_modrdn.modrdn_mods = copy_mods(sop->p.p_modrdn.modrdn_mods);
  393. }
  394. break;
  395. case SLAPI_OPERATION_DELETE:
  396. /* Has no extra parameters. */
  397. case SLAPI_OPERATION_BIND:
  398. case SLAPI_OPERATION_COMPARE:
  399. case SLAPI_OPERATION_SEARCH:
  400. default:
  401. /* We are not interested in these. */
  402. break;
  403. }
  404. return sop_new;
  405. }
  406. void
  407. operation_parameters_done (struct slapi_operation_parameters *sop)
  408. {
  409. if(sop!=NULL)
  410. {
  411. slapi_ch_free((void **)&sop->target_address.dn);
  412. slapi_ch_free((void **)&sop->target_address.uniqueid);
  413. csn_free(&sop->csn);
  414. switch(sop->operation_type)
  415. {
  416. case SLAPI_OPERATION_ADD:
  417. slapi_entry_free(sop->p.p_add.target_entry);
  418. sop->p.p_add.target_entry= NULL;
  419. slapi_ch_free((void **)&(sop->p.p_add.parentuniqueid));
  420. break;
  421. case SLAPI_OPERATION_MODIFY:
  422. ldap_mods_free(sop->p.p_modify.modify_mods, 1 /* Free the Array and the Elements */);
  423. sop->p.p_modify.modify_mods= NULL;
  424. break;
  425. case SLAPI_OPERATION_MODRDN:
  426. slapi_ch_free((void **)&(sop->p.p_modrdn.modrdn_newrdn));
  427. slapi_ch_free((void **)&(sop->p.p_modrdn.modrdn_newsuperior_address.dn));
  428. slapi_ch_free((void **)&(sop->p.p_modrdn.modrdn_newsuperior_address.uniqueid));
  429. ldap_mods_free(sop->p.p_modrdn.modrdn_mods, 1 /* Free the Array and the Elements */);
  430. sop->p.p_modrdn.modrdn_mods= NULL;
  431. break;
  432. case SLAPI_OPERATION_DELETE:
  433. /* Has no extra parameters. */
  434. case SLAPI_OPERATION_BIND:
  435. case SLAPI_OPERATION_COMPARE:
  436. case SLAPI_OPERATION_SEARCH:
  437. default:
  438. /* We are not interested in these */
  439. break;
  440. }
  441. }
  442. }
  443. void operation_parameters_free(struct slapi_operation_parameters **sop)
  444. {
  445. if (sop)
  446. {
  447. operation_parameters_done (*sop);
  448. slapi_ch_free ((void**)sop);
  449. }
  450. }