plugin_internal_op.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927
  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. /* [email protected] June 13 1997 */
  42. #include <stdio.h>
  43. #include <sys/types.h>
  44. #include "slapi-plugin.h"
  45. #include "slap.h"
  46. #include <ssl.h>
  47. /* entry list node */
  48. typedef struct Entry_Node{
  49. Slapi_Entry *data;
  50. struct Entry_Node *next;
  51. } Entry_Node;
  52. /* referral list node */
  53. typedef struct Referral_Node{
  54. char *data;
  55. struct Referral_Node *next;
  56. } Referral_Node;
  57. /* data that must be passed to slapi_search_internal_callback */
  58. typedef struct plugin_search_internal_data{
  59. int rc;
  60. int num_entries;
  61. int num_referrals;
  62. Entry_Node *entry_list_head;
  63. Referral_Node *referral_list_head;
  64. } plugin_search_internal_data;
  65. /* callback functions */
  66. typedef struct callback_fn_ptrs{
  67. plugin_result_callback p_res_callback;
  68. plugin_search_entry_callback p_srch_entry_callback;
  69. plugin_referral_entry_callback p_ref_entry_callback;
  70. void *callback_data;
  71. }callback_fn_ptrs;
  72. /* forward declarations */
  73. static int seq_internal_callback_pb (Slapi_PBlock *pb, void *callback_data,
  74. plugin_result_callback prc,
  75. plugin_search_entry_callback psec,
  76. plugin_referral_entry_callback prec);
  77. static int search_internal_pb (Slapi_PBlock *pb);
  78. static int search_internal_callback_pb (Slapi_PBlock *pb, void *callback_data, plugin_result_callback prc,
  79. plugin_search_entry_callback psec, plugin_referral_entry_callback prec);
  80. void
  81. internal_getresult_callback(struct conn *unused1,
  82. struct op *op,
  83. int err,
  84. char *unused2,
  85. char *unused3,
  86. int unused4,
  87. struct berval **unused5)
  88. {
  89. if (op != NULL)
  90. {
  91. *((int *)op->o_handler_data) = err;
  92. }
  93. }
  94. void
  95. internal_res_callback(struct conn *unused1, struct op *op, int err, char *unused2,
  96. char *unused3, int unused4, struct berval **unused5)
  97. {
  98. /* make sure the user has a callback defined, if so do it, otherwise do nothing */
  99. if( ((callback_fn_ptrs *)op->o_handler_data) != NULL
  100. && ((callback_fn_ptrs *)op->o_handler_data)->p_res_callback != NULL
  101. )
  102. {
  103. ((callback_fn_ptrs *)op->o_handler_data)->p_res_callback
  104. (err, ((callback_fn_ptrs *)op->o_handler_data)->callback_data);
  105. }
  106. }
  107. int
  108. internal_srch_entry_callback(Slapi_Backend* be, Connection* conn,
  109. Operation* op, Slapi_Entry* e)
  110. {
  111. /* make sure the user has a callback defined, if so do it, otherwise do nothing */
  112. if( ((callback_fn_ptrs *)op->o_handler_data) != NULL
  113. && ((callback_fn_ptrs *)op->o_handler_data)->p_srch_entry_callback != NULL
  114. )
  115. {
  116. return(((callback_fn_ptrs *)op->o_handler_data)->p_srch_entry_callback
  117. (e, ((callback_fn_ptrs *)op->o_handler_data)->callback_data));
  118. }
  119. return(0);
  120. }
  121. int
  122. internal_ref_entry_callback(Slapi_Backend * be, Connection *conn,
  123. Operation *op, struct berval **ireferral)
  124. {
  125. int i;
  126. /* make sure the user has a callback defined, if so do it, otherwise do nothing */
  127. if( ((callback_fn_ptrs *)op->o_handler_data) != NULL
  128. && ((callback_fn_ptrs *)op->o_handler_data)->p_ref_entry_callback != NULL
  129. && ireferral != NULL
  130. )
  131. {
  132. /* loop over referrals calling callback for each one */
  133. for(i=0; ireferral[i] != NULL; i++)
  134. {
  135. ((callback_fn_ptrs *)op->o_handler_data)->p_ref_entry_callback(ireferral[i]->bv_val,
  136. ((callback_fn_ptrs *)op->o_handler_data)->callback_data);
  137. }
  138. }
  139. return(0);
  140. }
  141. Slapi_Operation*
  142. internal_operation_new(unsigned long op_type, int flags)
  143. {
  144. Slapi_Operation *op= operation_new(flags | OP_FLAG_INTERNAL /*Internal*/);
  145. /* set operation type: add, delete, etc */
  146. operation_set_type(op,op_type);
  147. /* Call the plugin extension constructors */
  148. op->o_extension = factory_create_extension(get_operation_object_type(),op,NULL /* Parent */);
  149. return op;
  150. }
  151. /******************************************************************************
  152. *
  153. * do_disconnect_server
  154. *
  155. *
  156. *
  157. *
  158. *******************************************************************************/
  159. /* this is just a wrapper exposed to the plugins */
  160. void
  161. slapi_disconnect_server(Slapi_Connection *conn)
  162. {
  163. do_disconnect_server(conn, conn->c_connid, -1);
  164. }
  165. static get_disconnect_server_fn_ptr disconnect_server_fn = NULL;
  166. void
  167. do_disconnect_server(Connection *conn, PRUint64 opconnid, int opid)
  168. {
  169. if (NULL == disconnect_server_fn) {
  170. if (get_entry_point(ENTRY_POINT_DISCONNECT_SERVER, (caddr_t *)(&disconnect_server_fn)) < 0) {
  171. return;
  172. }
  173. }
  174. /* It seems that we only call this from result.c when the ber_flush fails. */
  175. (disconnect_server_fn)(conn, opconnid, opid, SLAPD_DISCONNECT_BER_FLUSH, 0);
  176. }
  177. /******************************************************************************
  178. *
  179. * slapi_compare_internal
  180. *
  181. * no plans to implement this, but placeholder incase we change our mind
  182. *
  183. *
  184. *******************************************************************************/
  185. Slapi_PBlock *
  186. slapi_compare_internal(char * dn,
  187. char *attr,
  188. char *value,
  189. LDAPControl **controls)
  190. {
  191. printf("slapi_compare_internal not yet implemented \n");
  192. return(0);
  193. }
  194. int
  195. slapi_seq_callback( const char *ibase,
  196. int type,
  197. char *attrname,
  198. char *val,
  199. char **attrs,
  200. int attrsonly,
  201. void *callback_data,
  202. LDAPControl **controls,
  203. plugin_result_callback res_callback,
  204. plugin_search_entry_callback srch_callback,
  205. plugin_referral_entry_callback ref_callback)
  206. {
  207. int r;
  208. Slapi_PBlock pb;
  209. if (ibase == NULL)
  210. {
  211. slapi_log_error(SLAPI_LOG_FATAL, NULL,
  212. "slapi_seq_callback: NULL parameter\n");
  213. return -1;
  214. }
  215. pblock_init(&pb);
  216. slapi_seq_internal_set_pb(&pb, (char *)ibase, type, attrname, val, attrs, attrsonly, controls,
  217. plugin_get_default_component_id(), 0);
  218. r= seq_internal_callback_pb (&pb, callback_data, res_callback, srch_callback, ref_callback);
  219. pblock_done(&pb);
  220. return r;
  221. }
  222. /* pblock should contain the following data (can be set via call to slapi_seq_internal_set_pb):
  223. SLAPI_SEARCH_TARGET set to search base
  224. SAPI_SEQ_TYPE set to sequential access type (SLAPI_SEQ_FIRST, SLAPI_SEQ_NEXT, etc.
  225. SLAPI_SEQ_ATTRNAME the next two fields define attribute value assertion
  226. SLAPI_SEQ_VAL relative to which access is performed.
  227. SLAPI_CONTROLS_ARG set to request controls if present
  228. SLAPI_SEARCH_ATTRS set to the list of attributes to return
  229. SLAPI_SEARCH_ATTRSONLY tells whether attribute values should be returned.
  230. */
  231. int slapi_seq_internal_callback_pb (Slapi_PBlock *pb, void *callback_data, plugin_result_callback res_callback,
  232. plugin_search_entry_callback srch_callback,
  233. plugin_referral_entry_callback ref_callback)
  234. {
  235. if (pb == NULL)
  236. return -1;
  237. if (!allow_operation (pb))
  238. {
  239. send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL,
  240. "This plugin is not configured to access operation target data", 0, NULL );
  241. return 0;
  242. }
  243. return (seq_internal_callback_pb (pb, callback_data, res_callback, srch_callback, ref_callback));
  244. }
  245. void slapi_search_internal_set_pb (Slapi_PBlock *pb, const char *base, int scope, const char *filter, char **attrs,
  246. int attrsonly, LDAPControl **controls, const char *uniqueid,
  247. Slapi_ComponentId *plugin_identity, int operation_flags)
  248. {
  249. Operation *op;
  250. if (pb == NULL || base == NULL)
  251. {
  252. slapi_log_error(SLAPI_LOG_FATAL, NULL,
  253. "slapi_search_internal_set_pb: NULL parameter\n");
  254. return;
  255. }
  256. op= internal_operation_new(SLAPI_OPERATION_SEARCH,operation_flags);
  257. slapi_pblock_set(pb, SLAPI_OPERATION, op);
  258. slapi_pblock_set(pb, SLAPI_SEARCH_TARGET, (void*)base);
  259. slapi_pblock_set(pb, SLAPI_SEARCH_SCOPE, &scope);
  260. slapi_pblock_set(pb, SLAPI_SEARCH_STRFILTER, (void*)filter);
  261. slapi_pblock_set(pb, SLAPI_CONTROLS_ARG, controls);
  262. slapi_pblock_set(pb, SLAPI_SEARCH_ATTRS, attrs);
  263. slapi_pblock_set(pb, SLAPI_SEARCH_ATTRSONLY, &attrsonly);
  264. if (uniqueid)
  265. {
  266. slapi_pblock_set(pb, SLAPI_TARGET_UNIQUEID, (void*)uniqueid);
  267. }
  268. slapi_pblock_set(pb, SLAPI_PLUGIN_IDENTITY, (void*)plugin_identity);
  269. }
  270. void slapi_seq_internal_set_pb(Slapi_PBlock *pb, char *base, int type, char *attrname, char *val,
  271. char **attrs, int attrsonly, LDAPControl **controls,
  272. Slapi_ComponentId *plugin_identity, int operation_flags)
  273. {
  274. Operation *op;
  275. if (pb == NULL || base == NULL)
  276. {
  277. slapi_log_error(SLAPI_LOG_FATAL, NULL,
  278. "slapi_seq_internal_set_pb: NULL parameter\n");
  279. return;
  280. }
  281. op= internal_operation_new(SLAPI_OPERATION_SEARCH,operation_flags);
  282. slapi_pblock_set(pb, SLAPI_OPERATION, op);
  283. slapi_pblock_set(pb, SLAPI_SEARCH_TARGET, base);
  284. slapi_pblock_set(pb, SLAPI_SEQ_TYPE, &type);
  285. slapi_pblock_set(pb, SLAPI_SEQ_ATTRNAME, attrname);
  286. slapi_pblock_set(pb, SLAPI_SEQ_VAL, val);
  287. slapi_pblock_set(pb, SLAPI_SEARCH_ATTRS, attrs);
  288. slapi_pblock_set(pb, SLAPI_SEARCH_ATTRSONLY, &attrsonly);
  289. slapi_pblock_set(pb, SLAPI_CONTROLS_ARG, controls);
  290. slapi_pblock_set(pb, SLAPI_PLUGIN_IDENTITY, plugin_identity);
  291. }
  292. static int seq_internal_callback_pb (Slapi_PBlock *pb, void *callback_data,
  293. plugin_result_callback prc,
  294. plugin_search_entry_callback psec,
  295. plugin_referral_entry_callback prec)
  296. {
  297. int rc;
  298. LDAPControl **controls;
  299. Operation *op;
  300. struct callback_fn_ptrs callback_handler_data;
  301. Slapi_Backend *be;
  302. Slapi_DN sdn;
  303. char *base;
  304. char *attrname, *val;
  305. slapi_pblock_get(pb, SLAPI_SEARCH_TARGET, &base);
  306. slapi_pblock_get(pb, SLAPI_CONTROLS_ARG, &controls);
  307. if (base == NULL) {
  308. slapi_sdn_init_dn_byval(&sdn,"");
  309. } else {
  310. slapi_sdn_init_dn_byval(&sdn, base);
  311. }
  312. be = slapi_be_select(&sdn);
  313. callback_handler_data.p_res_callback = prc;
  314. callback_handler_data.p_srch_entry_callback = psec;
  315. callback_handler_data.p_ref_entry_callback = prec;
  316. callback_handler_data.callback_data = callback_data;
  317. slapi_pblock_get(pb, SLAPI_OPERATION, &op);
  318. op->o_handler_data = (void *)&callback_handler_data;
  319. op->o_result_handler = internal_res_callback;
  320. op->o_search_entry_handler = internal_srch_entry_callback;
  321. op->o_search_referral_handler = internal_ref_entry_callback;
  322. /* set target specification of the operation used to decide which plugins are called for the operation */
  323. operation_set_target_spec (op, &sdn);
  324. /* Normalize the attribute type and value */
  325. slapi_pblock_get (pb, SLAPI_SEQ_ATTRNAME, &attrname);
  326. slapi_pblock_get (pb, SLAPI_SEQ_VAL, &val);
  327. attrname = slapi_attr_syntax_normalize(attrname);
  328. val = ( NULL == val ) ? NULL : slapi_ch_strdup( val );
  329. slapi_pblock_set(pb, SLAPI_BACKEND, be);
  330. slapi_pblock_set(pb, SLAPI_PLUGIN, be->be_database);
  331. slapi_pblock_set(pb, SLAPI_SEQ_ATTRNAME, attrname);
  332. slapi_pblock_set(pb, SLAPI_SEQ_VAL, val);
  333. slapi_pblock_set(pb, SLAPI_REQCONTROLS, controls);
  334. /* set actions taken to process the operation */
  335. set_config_params (pb);
  336. /* set common parameters */
  337. set_common_params (pb);
  338. if (be->be_seq != NULL)
  339. {
  340. rc = (*be->be_seq)(pb);
  341. }
  342. else
  343. {
  344. send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "Function not implemented", 0, NULL);
  345. rc = 0;
  346. }
  347. slapi_ch_free((void **) &attrname);
  348. slapi_ch_free((void **) &val);
  349. slapi_sdn_done(&sdn);
  350. return rc;
  351. }
  352. int
  353. slapi_search_internal_callback(const char *ibase,
  354. int scope,
  355. const char *ifstr,
  356. char **attrs,
  357. int attrsonly,
  358. void *callback_data,
  359. LDAPControl **controls,
  360. plugin_result_callback res_callback,
  361. plugin_search_entry_callback srch_callback,
  362. plugin_referral_entry_callback ref_callback)
  363. {
  364. Slapi_PBlock pb;
  365. int rc = 0;
  366. pblock_init(&pb);
  367. slapi_search_internal_set_pb (&pb, ibase, scope, ifstr, attrs, attrsonly,
  368. controls, NULL, plugin_get_default_component_id(), 0);
  369. rc = search_internal_callback_pb (&pb, callback_data, res_callback,
  370. srch_callback, ref_callback);
  371. pblock_done(&pb);
  372. return (rc);
  373. }
  374. Slapi_PBlock *
  375. slapi_search_internal(const char *base,
  376. int scope,
  377. const char *filter,
  378. LDAPControl **controls,
  379. char **attrs,
  380. int attrsonly)
  381. {
  382. Slapi_PBlock *pb;
  383. /* initialize pb */
  384. pb = slapi_pblock_new();
  385. if (pb)
  386. {
  387. slapi_search_internal_set_pb (pb, base, scope, filter, attrs, attrsonly, controls,
  388. NULL, plugin_get_default_component_id(), 0);
  389. search_internal_pb (pb);
  390. }
  391. return pb;
  392. }
  393. /* This function free searchs result or referral set on internal_ops in pblocks */
  394. void
  395. slapi_free_search_results_internal(Slapi_PBlock *pb)
  396. {
  397. int i;
  398. if(pb == NULL)
  399. {
  400. return;
  401. }
  402. if(pb->pb_plugin_internal_search_op_entries != NULL)
  403. {
  404. for(i=0; pb->pb_plugin_internal_search_op_entries[i] != NULL; i++)
  405. {
  406. slapi_entry_free(pb->pb_plugin_internal_search_op_entries[i]);
  407. }
  408. slapi_ch_free((void**)&(pb->pb_plugin_internal_search_op_entries));
  409. }
  410. /* free v3 referrals made from result handler */
  411. if(pb->pb_plugin_internal_search_op_referrals != NULL)
  412. {
  413. for(i=0; pb->pb_plugin_internal_search_op_referrals[i] != NULL; i++)
  414. {
  415. slapi_ch_free((void**)&(pb->pb_plugin_internal_search_op_referrals[i]));
  416. }
  417. slapi_ch_free((void**)&(pb->pb_plugin_internal_search_op_referrals));
  418. }
  419. }
  420. /* this functions can be used for dn as well as uniqueid based operations */
  421. /* pblock should contain the following data (can be set via call to slapi_search_internal_set_pb):
  422. For uniqueid based search:
  423. SLAPI_TARGET_DN set to dn that allows to select right backend
  424. SLAPI_TARGET_UNIQUEID set to the uniqueid of the entry we are looking for
  425. For dn based search:
  426. SLAPI_TARGET_DN set to search base
  427. SLAPI_ORIGINAL_TARGET_DN set to original un-normalized search base
  428. SLAPI_SEARCH_SCOPE set to search scope
  429. SLAPI_SEARCH_STRFILTER set to search filter
  430. SLAPI_CONTROLS_ARG set to request controls if present
  431. SLAPI_SEARCH_ATTRS set to the list of attributes to return
  432. SLAPI_SEARCH_ATTRSONLY tells whether attribute values should be returned.
  433. */
  434. int slapi_search_internal_pb (Slapi_PBlock *pb)
  435. {
  436. if (pb == NULL)
  437. return -1;
  438. if (!allow_operation (pb))
  439. {
  440. slapi_send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL,
  441. "This plugin is not configured to access operation target data", 0, NULL );
  442. return 0;
  443. }
  444. return search_internal_pb (pb);
  445. }
  446. /* pblock should contain the same data as for slapi_search_internal_pb */
  447. int slapi_search_internal_callback_pb (Slapi_PBlock *pb, void *callback_data,
  448. plugin_result_callback prc,
  449. plugin_search_entry_callback psec,
  450. plugin_referral_entry_callback prec)
  451. {
  452. if (pb == NULL)
  453. return -1;
  454. if (!allow_operation (pb))
  455. {
  456. send_ldap_result( pb, LDAP_UNWILLING_TO_PERFORM, NULL,
  457. "This plugin is not configured to access operation target data", 0, NULL );
  458. return 0;
  459. }
  460. return (search_internal_callback_pb (pb, callback_data, prc, psec, prec));
  461. }
  462. static int
  463. internal_plugin_search_entry_callback(Slapi_Entry *e, void *callback_data)
  464. {
  465. Entry_Node *this_entry;
  466. /* add this entry to the list of entries we are making */
  467. this_entry = (Entry_Node *)slapi_ch_calloc(1,sizeof(Entry_Node));
  468. if ((this_entry->data = slapi_entry_dup(e)) == NULL)
  469. {
  470. return(0);
  471. }
  472. this_entry->next = ((plugin_search_internal_data *) callback_data)->entry_list_head;
  473. ((plugin_search_internal_data *) callback_data)->entry_list_head = this_entry;
  474. ((plugin_search_internal_data *) callback_data)->num_entries++;
  475. return(0);
  476. }
  477. static int
  478. internal_plugin_search_referral_callback(char *referral, void *callback_data)
  479. {
  480. Referral_Node *this_referral;
  481. /* add this to the list of referrals we are making */
  482. this_referral = (Referral_Node *)slapi_ch_calloc(1,sizeof(Referral_Node));
  483. this_referral->data = slapi_ch_strdup(referral);
  484. this_referral->next = ((plugin_search_internal_data *) callback_data)->referral_list_head;
  485. ((plugin_search_internal_data *) callback_data)->referral_list_head = this_referral;
  486. ((plugin_search_internal_data *) callback_data)->num_referrals++;
  487. return(0);
  488. }
  489. static void internal_plugin_result_callback(int rc, void *callback_data)
  490. {
  491. /* put the result into pb_op_result */
  492. ((plugin_search_internal_data *) callback_data)->rc = rc;
  493. }
  494. static int search_internal_pb (Slapi_PBlock *pb)
  495. {
  496. plugin_search_internal_data psid;
  497. Entry_Node *iterator, *tmp;
  498. Referral_Node *ref_iterator, *ref_tmp;
  499. int i;
  500. int opresult = 0;
  501. Slapi_Entry **pb_search_entries = NULL;
  502. char **pb_search_referrals = NULL;
  503. PR_ASSERT (pb);
  504. /* initialize psid */
  505. psid.rc = -1;
  506. psid.num_entries =0;
  507. psid.num_referrals =0;
  508. psid.entry_list_head = NULL;
  509. psid.referral_list_head = NULL;
  510. /* setup additional pb data */
  511. slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_RESULT, &opresult);
  512. slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, pb_search_entries);
  513. slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_SEARCH_REFERRALS, pb_search_referrals);
  514. /* call internal search callback, define search_entry_callback, and result_callback such
  515. that the results of the search are stuffed into pb */
  516. search_internal_callback_pb (pb, &psid, internal_plugin_result_callback,
  517. internal_plugin_search_entry_callback,
  518. internal_plugin_search_referral_callback);
  519. opresult = psid.rc;
  520. /* stuff search entry pointers from linked list to contiguous array for pblock */
  521. pb_search_entries = (Slapi_Entry **)slapi_ch_calloc((psid.num_entries + 1), sizeof(Slapi_Entry *));
  522. for(i=0,iterator = psid.entry_list_head; iterator !=NULL; iterator=iterator->next, i++)
  523. {
  524. pb_search_entries[i]= iterator->data;
  525. }
  526. pb_search_entries[i]=NULL;
  527. /* free the linked list now that data has been put in the array */
  528. iterator=psid.entry_list_head;
  529. while(iterator != NULL)
  530. {
  531. /* free the data held in this node */
  532. tmp = iterator;
  533. iterator = iterator->next;
  534. /* free the node */
  535. if(tmp != NULL)
  536. {
  537. slapi_ch_free((void **) &tmp);
  538. }
  539. }
  540. psid.entry_list_head = NULL;
  541. /* stuff referrals list into an array if we got any to put into the pblock */
  542. if(psid.num_referrals != 0)
  543. {
  544. pb_search_referrals = (char **)slapi_ch_calloc((psid.num_referrals + 1), sizeof(char *));
  545. for(i=0, ref_iterator = psid.referral_list_head; ref_iterator !=NULL; ref_iterator=ref_iterator->next, i++)
  546. {
  547. pb_search_referrals[i]= ref_iterator->data;
  548. }
  549. pb_search_referrals[i]=NULL;
  550. /* free the linked list now that data has been put in the array */
  551. ref_iterator=psid.referral_list_head;
  552. while(ref_iterator != NULL)
  553. {
  554. ref_tmp = ref_iterator;
  555. ref_iterator = ref_iterator->next;
  556. /* free the node */
  557. if(ref_tmp != NULL)
  558. {
  559. slapi_ch_free((void **) &ref_tmp);
  560. }
  561. }
  562. psid.referral_list_head = NULL;
  563. }
  564. /* set the result, the array of entries, and the array of referrals in pb */
  565. slapi_pblock_set(pb, SLAPI_NENTRIES, &psid.num_entries);
  566. slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_RESULT, &opresult);
  567. slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, pb_search_entries);
  568. slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_SEARCH_REFERRALS, pb_search_referrals);
  569. return 0;
  570. }
  571. static int search_internal_callback_pb (Slapi_PBlock *pb, void *callback_data,
  572. plugin_result_callback prc,
  573. plugin_search_entry_callback psec,
  574. plugin_referral_entry_callback prec)
  575. {
  576. LDAPControl **controls;
  577. Operation *op;
  578. struct slapi_filter *filter = NULL;
  579. char *fstr = NULL;
  580. struct callback_fn_ptrs callback_handler_data;
  581. int scope;
  582. char *ifstr;
  583. int opresult;
  584. int rc = 0;
  585. char *original_base = 0;
  586. char *new_base = 0;
  587. PR_ASSERT (pb);
  588. /* retrieve search parameters */
  589. slapi_pblock_get(pb, SLAPI_SEARCH_SCOPE, &scope);
  590. slapi_pblock_get(pb, SLAPI_SEARCH_STRFILTER, &ifstr);
  591. slapi_pblock_get(pb, SLAPI_CONTROLS_ARG, &controls);
  592. /* data validation */
  593. if (ifstr == NULL || (scope != LDAP_SCOPE_BASE && scope != LDAP_SCOPE_ONELEVEL
  594. && scope != LDAP_SCOPE_SUBTREE))
  595. {
  596. opresult = LDAP_PARAM_ERROR;
  597. slapi_pblock_set(pb, SLAPI_PLUGIN_INTOP_RESULT, &opresult);
  598. return -1;
  599. }
  600. callback_handler_data.p_res_callback = prc;
  601. callback_handler_data.p_srch_entry_callback = psec;
  602. callback_handler_data.p_ref_entry_callback = prec;
  603. callback_handler_data.callback_data = callback_data;
  604. slapi_pblock_get(pb, SLAPI_OPERATION, &op);
  605. op->o_handler_data = (void *)&callback_handler_data;
  606. op->o_result_handler = internal_res_callback;
  607. op->o_search_entry_handler = internal_srch_entry_callback;
  608. op->o_search_referral_handler = internal_ref_entry_callback;
  609. filter = slapi_str2filter((fstr = slapi_ch_strdup(ifstr)));
  610. if(scope == LDAP_SCOPE_BASE) {
  611. filter->f_flags |= (SLAPI_FILTER_LDAPSUBENTRY |
  612. SLAPI_FILTER_TOMBSTONE | SLAPI_FILTER_RUV);
  613. }
  614. if (NULL == filter)
  615. {
  616. send_ldap_result(pb, LDAP_FILTER_ERROR, NULL, NULL, 0, NULL);
  617. rc = -1;
  618. goto done;
  619. }
  620. filter_normalize(filter);
  621. slapi_pblock_set(pb, SLAPI_SEARCH_FILTER, filter);
  622. slapi_pblock_set(pb, SLAPI_REQCONTROLS, controls);
  623. /* set actions taken to process the operation */
  624. set_config_params (pb);
  625. /* set parameters common for all internal operations */
  626. set_common_params (pb);
  627. {
  628. int timelimit = -1;
  629. int sizelimit = -1;
  630. int deref = LDAP_DEREF_ALWAYS;
  631. slapi_pblock_set(pb, SLAPI_SEARCH_DEREF, &deref);
  632. slapi_pblock_set(pb, SLAPI_SEARCH_TIMELIMIT, &timelimit);
  633. slapi_pblock_set(pb, SLAPI_SEARCH_SIZELIMIT, &sizelimit);
  634. }
  635. /* plugins which play with the search may
  636. * change the search params may allocate
  637. * memory so we need to keep track of
  638. * changed base search strings
  639. */
  640. slapi_pblock_get(pb, SLAPI_SEARCH_TARGET, &original_base);
  641. slapi_pblock_set(pb, SLAPI_ORIGINAL_TARGET_DN, slapi_ch_strdup(original_base));
  642. op_shared_search (pb, 1);
  643. slapi_pblock_get(pb, SLAPI_SEARCH_TARGET, &new_base);
  644. slapi_pblock_get(pb, SLAPI_SEARCH_FILTER, &filter);
  645. done:
  646. slapi_ch_free((void **) & fstr);
  647. if (filter != NULL)
  648. {
  649. slapi_filter_free(filter, 1 /* recurse */);
  650. }
  651. if(original_base != new_base)
  652. slapi_ch_free_string(&new_base);
  653. /* we strdup'd this above - need to free */
  654. slapi_pblock_get(pb, SLAPI_ORIGINAL_TARGET_DN, &original_base);
  655. slapi_ch_free_string(&original_base);
  656. return(rc);
  657. }
  658. /* allow/disallow operation based of the plugin configuration */
  659. PRBool allow_operation (Slapi_PBlock *pb)
  660. {
  661. char *dn = NULL;
  662. struct slapdplugin *plugin = NULL;
  663. Slapi_DN sdn;
  664. PRBool allow;
  665. struct slapi_componentid * cid=NULL;
  666. PR_ASSERT (pb);
  667. /* make sure that users of new API provide plugin identity */
  668. slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &cid);
  669. if (cid == NULL)
  670. {
  671. slapi_log_error( SLAPI_LOG_FATAL, NULL, "allow_operation: component identity is NULL\n");
  672. return PR_FALSE;
  673. }
  674. plugin=(struct slapdplugin *) cid->sci_plugin;
  675. if (plugin == NULL)
  676. {
  677. slapi_log_error( SLAPI_LOG_FATAL, NULL, "allow_operation: plugin identity is NULL\n");
  678. return PR_FALSE;
  679. }
  680. slapi_pblock_get (pb, SLAPI_TARGET_DN, &dn);
  681. if (dn == NULL) {
  682. slapi_sdn_init_dn_byval(&sdn,"");
  683. } else {
  684. slapi_sdn_init_dn_byval(&sdn, dn);
  685. }
  686. allow = plugin_allow_internal_op (&sdn, plugin);
  687. slapi_sdn_done (&sdn);
  688. return allow;
  689. }
  690. /* set operation configuration based on the plugin configuration */
  691. void set_config_params (Slapi_PBlock *pb)
  692. {
  693. Slapi_Operation *operation;
  694. struct slapdplugin *plugin = NULL;
  695. char *dn;
  696. struct slapi_componentid * cid=NULL;
  697. slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &cid);
  698. if (cid)
  699. plugin=(struct slapdplugin *) cid->sci_plugin;
  700. /* set actions */
  701. slapi_pblock_get( pb, SLAPI_OPERATION, &operation);
  702. operation_set_flag(operation,plugin_build_operation_action_bitmap(operation->o_flags, plugin));
  703. /* Check if we have a flag to keep the operation secret */
  704. if (operation_is_flag_set(operation, OP_FLAG_ACTION_NOLOG)) {
  705. /* Clear the LOG_AUDIT and LOG_CHANGES flag */
  706. operation_clear_flag(operation, OP_FLAG_ACTION_LOG_AUDIT | OP_FLAG_ACTION_LOG_CHANGES);
  707. }
  708. /* set name to be used for creator's and modifiers attributes */
  709. dn = plugin_get_dn (plugin);
  710. if (dn)
  711. slapi_sdn_init_dn_passin(&operation->o_sdn, dn);
  712. }
  713. /* set parameters common for all internal operations */
  714. void set_common_params (Slapi_PBlock *pb)
  715. {
  716. int isroot = 1;
  717. LDAPControl **controls;
  718. slapi_pblock_get(pb, SLAPI_CONTROLS_ARG, &controls);
  719. if (NULL != controls)
  720. {
  721. int managedsait = slapi_control_present(controls,
  722. LDAP_CONTROL_MANAGEDSAIT, NULL, NULL);
  723. int pwpolicy_ctrl = slapi_control_present(controls,
  724. LDAP_X_CONTROL_PWPOLICY_REQUEST, NULL, NULL);
  725. slapi_pblock_set(pb, SLAPI_MANAGEDSAIT, &managedsait);
  726. slapi_pblock_set(pb, SLAPI_PWPOLICY, &pwpolicy_ctrl);
  727. }
  728. slapi_pblock_set(pb, SLAPI_REQUESTOR_ISROOT, &isroot);
  729. }
  730. /*
  731. * Given a DN, find an entry by doing an internal search. An LDAP error
  732. * code is returned. To check if an entry exists without returning a
  733. * copy of the entry, NULL can be passed for ret_entry.
  734. */
  735. int
  736. slapi_search_internal_get_entry_ext( Slapi_DN *dn, char ** attrs, Slapi_Entry **ret_entry , void * component_identity, void *txn )
  737. {
  738. Slapi_Entry **entries = NULL;
  739. Slapi_PBlock *int_search_pb = NULL;
  740. int rc = 0;
  741. if (ret_entry) {
  742. *ret_entry = NULL;
  743. }
  744. int_search_pb = slapi_pblock_new ();
  745. slapi_search_internal_set_pb ( int_search_pb, slapi_sdn_get_dn(dn), LDAP_SCOPE_BASE, "(|(objectclass=*)(objectclass=ldapsubentry))",
  746. attrs ,
  747. 0 /* attrsonly */, NULL /* controls */,
  748. NULL /* uniqueid */,
  749. component_identity, 0 /* actions */ );
  750. slapi_pblock_set( int_search_pb, SLAPI_TXN, txn );
  751. slapi_search_internal_pb ( int_search_pb );
  752. slapi_pblock_get( int_search_pb, SLAPI_PLUGIN_INTOP_RESULT, &rc );
  753. if ( LDAP_SUCCESS == rc ) {
  754. slapi_pblock_get( int_search_pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries );
  755. if ( NULL != entries && NULL != entries[ 0 ]) {
  756. /* Only need to dup the entry if the caller passed ret_entry in. */
  757. if (ret_entry) {
  758. Slapi_Entry *temp_entry = NULL;
  759. temp_entry = entries[ 0 ];
  760. *ret_entry = slapi_entry_dup(temp_entry);
  761. }
  762. } else {
  763. /* No entry there */
  764. rc = LDAP_NO_SUCH_OBJECT;
  765. }
  766. }
  767. slapi_free_search_results_internal(int_search_pb);
  768. slapi_pblock_destroy(int_search_pb);
  769. int_search_pb = NULL;
  770. return rc;
  771. }
  772. /*
  773. * Given a DN, find an entry by doing an internal search. An LDAP error
  774. * code is returned. To check if an entry exists without returning a
  775. * copy of the entry, NULL can be passed for ret_entry.
  776. */
  777. int
  778. slapi_search_internal_get_entry( Slapi_DN *dn, char ** attrs, Slapi_Entry **ret_entry , void * component_identity)
  779. {
  780. return slapi_search_internal_get_entry_ext(dn, attrs, ret_entry, component_identity, NULL);
  781. }