plugin_internal_op.c 29 KB

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