ldbm_search.c 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491
  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. /* search.c - ldbm backend search function */
  42. /* view with ts=4 */
  43. #include "back-ldbm.h"
  44. #include "vlv_srch.h"
  45. /* prototypes */
  46. static int build_candidate_list( Slapi_PBlock *pb, backend *be,
  47. struct backentry *e, const char * base, int scope,
  48. int *lookup_returned_allidsp, IDList** candidates);
  49. static IDList *base_candidates( Slapi_PBlock *pb, struct backentry *e );
  50. static IDList *onelevel_candidates( Slapi_PBlock *pb, backend *be, const char *base, struct backentry *e, Slapi_Filter *filter, int managedsait, int *lookup_returned_allidsp, int *err );
  51. static back_search_result_set* new_search_result_set(IDList* idl,int vlv, int lookthroughlimit);
  52. static void delete_search_result_set( back_search_result_set **sr );
  53. static int can_skip_filter_test( Slapi_PBlock *pb, struct slapi_filter *f,
  54. int scope, IDList *idl );
  55. /* This is for performance testing, allows us to disable ACL checking altogether */
  56. #if defined(DISABLE_ACL_CHECK)
  57. #define ACL_CHECK_FLAG 0
  58. #else
  59. #define ACL_CHECK_FLAG 1
  60. #endif
  61. #define ISLEGACY(be) (be?(be->be_instance_info?(((ldbm_instance *)be->be_instance_info)->inst_li?(((ldbm_instance *)be->be_instance_info)->inst_li->li_legacy_errcode):0):0):0)
  62. int
  63. compute_lookthrough_limit( Slapi_PBlock *pb, struct ldbminfo *li )
  64. {
  65. Slapi_Connection *conn = NULL;
  66. int limit;
  67. slapi_pblock_get( pb, SLAPI_CONNECTION, &conn);
  68. if ( slapi_reslimit_get_integer_limit( conn,
  69. li->li_reslimit_lookthrough_handle, &limit )
  70. != SLAPI_RESLIMIT_STATUS_SUCCESS ) {
  71. /*
  72. * no limit associated with binder/connection or some other error
  73. * occurred. use the default.
  74. */
  75. int isroot = 0;
  76. slapi_pblock_get( pb, SLAPI_REQUESTOR_ISROOT, &isroot );
  77. if (isroot) {
  78. limit = -1;
  79. } else {
  80. PR_Lock(li->li_config_mutex);
  81. limit = li->li_lookthroughlimit;
  82. PR_Unlock(li->li_config_mutex);
  83. }
  84. }
  85. return( limit );
  86. }
  87. /* don't free the berval, just clean it */
  88. static void
  89. berval_done(struct berval *val)
  90. {
  91. slapi_ch_free_string(&val->bv_val);
  92. }
  93. /*
  94. * We call this function as we exit ldbm_back_search
  95. */
  96. int ldbm_back_search_cleanup(Slapi_PBlock *pb, struct ldbminfo *li, sort_spec_thing *sort_control, int ldap_result, char* ldap_result_description, int function_result, Slapi_DN *sdn, struct vlv_request *vlv_request_control)
  97. {
  98. if(sort_control!=NULL)
  99. {
  100. sort_spec_free(sort_control);
  101. }
  102. if(ldap_result>=LDAP_SUCCESS)
  103. {
  104. slapi_send_ldap_result( pb, ldap_result, NULL, ldap_result_description, 0, NULL );
  105. }
  106. {
  107. /* hack hack --- code to free the result set if we don't need it */
  108. /* We get it and check to see if the structure was ever used */
  109. back_search_result_set *sr = NULL;
  110. slapi_pblock_get( pb, SLAPI_SEARCH_RESULT_SET, &sr );
  111. if ( (NULL != sr) && (function_result != 0) ) {
  112. /* in case paged results, clean up the conn */
  113. pagedresults_set_search_result(pb->pb_conn, NULL);
  114. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL );
  115. delete_search_result_set(&sr);
  116. }
  117. }
  118. slapi_sdn_done(sdn);
  119. if (vlv_request_control)
  120. {
  121. berval_done(&vlv_request_control->value);
  122. }
  123. return function_result;
  124. }
  125. /*
  126. * Return values from ldbm_back_search are:
  127. *
  128. * 0: Success. A result set is in the pblock. No results have been
  129. * sent to the client.
  130. * 1: Success. The result has already been sent to the client.
  131. * -1: An error occurred, and results have been sent to the client.
  132. * -2: Disk Full. Abandon ship!
  133. */
  134. int
  135. ldbm_back_search( Slapi_PBlock *pb )
  136. {
  137. /* Search stuff */
  138. backend *be;
  139. ldbm_instance *inst;
  140. struct ldbminfo *li;
  141. struct backentry *e;
  142. IDList *candidates= NULL;
  143. char *base;
  144. Slapi_DN basesdn;
  145. int scope;
  146. LDAPControl **controls = NULL;
  147. Slapi_Operation *operation;
  148. entry_address *addr;
  149. /* SORT control stuff */
  150. int sort = 0;
  151. int vlv = 0;
  152. struct berval *sort_spec = NULL;
  153. int is_sorting_critical = 0;
  154. int is_sorting_critical_orig = 0;
  155. sort_spec_thing *sort_control = NULL;
  156. /* VLV control stuff */
  157. int virtual_list_view = 0;
  158. struct berval *vlv_spec = NULL;
  159. int is_vlv_critical = 0;
  160. struct vlv_request vlv_request_control;
  161. back_search_result_set *sr = NULL;
  162. /* Fix for bugid #394184, SD, 20 Jul 00 */
  163. int tmp_err = -1; /* must be lower than LDAP_SUCCESS */
  164. char * tmp_desc = NULL;
  165. /* end Fix for defect #394184 */
  166. int lookup_returned_allids = 0;
  167. int backend_count = 1;
  168. static int print_once = 1;
  169. slapi_pblock_get( pb, SLAPI_BACKEND, &be );
  170. slapi_pblock_get( pb, SLAPI_OPERATION, &operation);
  171. slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
  172. slapi_pblock_get( pb, SLAPI_SEARCH_TARGET, &base );
  173. slapi_pblock_get( pb, SLAPI_TARGET_ADDRESS, &addr);
  174. slapi_pblock_get( pb, SLAPI_SEARCH_SCOPE, &scope );
  175. slapi_pblock_get( pb, SLAPI_REQCONTROLS, &controls );
  176. slapi_pblock_get( pb, SLAPI_BACKEND_COUNT, &backend_count );
  177. inst = (ldbm_instance *) be->be_instance_info;
  178. slapi_sdn_init_dn_ndn_byref(&basesdn,base); /* normalized by front end*/
  179. /* Initialize the result set structure here because we need to use it during search processing */
  180. /* Beware that if we exit this routine sideways, we might leak this structure */
  181. sr = new_search_result_set( NULL, 0,
  182. compute_lookthrough_limit( pb, li ));
  183. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, sr );
  184. /* clear this out so we can free it later */
  185. memset(&vlv_request_control, 0, sizeof(vlv_request_control));
  186. if ( NULL != controls )
  187. {
  188. /* Are we being asked to sort the results ? */
  189. sort = slapi_control_present( controls, LDAP_CONTROL_SORTREQUEST, &sort_spec, &is_sorting_critical_orig );
  190. if(sort)
  191. {
  192. int r= parse_sort_spec(sort_spec, &sort_control);
  193. if(r!=0)
  194. {
  195. /* Badly formed SORT control */
  196. return ldbm_back_search_cleanup(pb, li, sort_control, LDAP_PROTOCOL_ERROR, "Sort Control", SLAPI_FAIL_GENERAL, &basesdn, NULL);
  197. }
  198. /* set this operation includes the server side sorting */
  199. operation->o_flags |= OP_FLAG_SERVER_SIDE_SORTING;
  200. }
  201. is_sorting_critical = is_sorting_critical_orig;
  202. /* Are we to provide a virtual view of the list? */
  203. if ((vlv = slapi_control_present( controls, LDAP_CONTROL_VLVREQUEST, &vlv_spec, &is_vlv_critical)))
  204. {
  205. if(sort)
  206. {
  207. int r = vlv_parse_request_control( be, vlv_spec, &vlv_request_control );
  208. if(r!=LDAP_SUCCESS)
  209. {
  210. /* Badly formed VLV control */
  211. return ldbm_back_search_cleanup(pb, li, sort_control, r, "VLV Control", SLAPI_FAIL_GENERAL, &basesdn, &vlv_request_control);
  212. }
  213. {
  214. /* Access Control Check to see if the client is allowed to use the VLV Control. */
  215. Slapi_Entry *feature;
  216. char dn[128];
  217. char *dummyAttr = "dummy#attr";
  218. char *dummyAttrs[2] = { NULL, NULL };
  219. dummyAttrs[0] = dummyAttr;
  220. PR_snprintf(dn,sizeof(dn),"dn: oid=%s,cn=features,cn=config",LDAP_CONTROL_VLVREQUEST);
  221. feature= slapi_str2entry(dn,0);
  222. r= plugin_call_acl_plugin (pb, feature, dummyAttrs, NULL, SLAPI_ACL_READ, ACLPLUGIN_ACCESS_DEFAULT, NULL);
  223. slapi_entry_free(feature);
  224. if(r!=LDAP_SUCCESS)
  225. {
  226. /* Client isn't allowed to do this. */
  227. return ldbm_back_search_cleanup(pb, li, sort_control, r, "VLV Control", SLAPI_FAIL_GENERAL, &basesdn, &vlv_request_control);
  228. }
  229. }
  230. /*
  231. * Sorting must always be critical for VLV; Force it be so.
  232. */
  233. is_sorting_critical= 1;
  234. virtual_list_view= 1;
  235. }
  236. else
  237. {
  238. /* Can't have a VLV control without a SORT control */
  239. return ldbm_back_search_cleanup(pb, li, sort_control, LDAP_SORT_CONTROL_MISSING, "VLV Control", SLAPI_FAIL_GENERAL, &basesdn, &vlv_request_control);
  240. }
  241. }
  242. }
  243. if ((virtual_list_view || sort) && backend_count > 0)
  244. {
  245. char *ctrlstr = NULL;
  246. struct vlv_response vlv_response = {0};
  247. if (virtual_list_view)
  248. {
  249. if (sort)
  250. {
  251. ctrlstr = "The VLV and sort controls cannot be processed";
  252. }
  253. else
  254. {
  255. ctrlstr = "The VLV control cannot be processed";
  256. }
  257. }
  258. else
  259. {
  260. if (sort)
  261. {
  262. ctrlstr = "The sort control cannot be processed";
  263. }
  264. }
  265. PR_ASSERT(NULL != ctrlstr);
  266. if (print_once)
  267. {
  268. LDAPDebug(LDAP_DEBUG_ANY,
  269. "ERROR: %s "
  270. "when more than one backend is involved. "
  271. "VLV indexes that will never be used should be removed.\n",
  272. ctrlstr, 0, 0);
  273. print_once = 0;
  274. }
  275. /* 402380: mapping tree must refuse VLV and SORT control
  276. * when several backends are impacted by a search */
  277. if (0 != is_vlv_critical)
  278. {
  279. vlv_response.result = LDAP_UNWILLING_TO_PERFORM;
  280. vlv_make_response_control(pb, &vlv_response);
  281. if (sort)
  282. {
  283. sort_make_sort_response_control(pb, LDAP_UNWILLING_TO_PERFORM, NULL);
  284. }
  285. if (ISLEGACY(be))
  286. {
  287. return ldbm_back_search_cleanup(pb, li, sort_control,
  288. LDAP_UNWILLING_TO_PERFORM, ctrlstr,
  289. SLAPI_FAIL_GENERAL, &basesdn, &vlv_request_control);
  290. }
  291. else
  292. {
  293. return ldbm_back_search_cleanup(pb, li, sort_control,
  294. LDAP_VIRTUAL_LIST_VIEW_ERROR, ctrlstr,
  295. SLAPI_FAIL_GENERAL, &basesdn, &vlv_request_control);
  296. }
  297. }
  298. else
  299. {
  300. if (0 != is_sorting_critical_orig)
  301. {
  302. if (virtual_list_view)
  303. {
  304. vlv_response.result = LDAP_UNWILLING_TO_PERFORM;
  305. vlv_make_response_control(pb, &vlv_response);
  306. }
  307. sort_make_sort_response_control(pb, LDAP_UNWILLING_TO_PERFORM, NULL);
  308. return ldbm_back_search_cleanup(pb, li, sort_control,
  309. LDAP_UNAVAILABLE_CRITICAL_EXTENSION, ctrlstr,
  310. SLAPI_FAIL_GENERAL, &basesdn, &vlv_request_control);
  311. }
  312. else /* vlv and sorting are not critical, so ignore the control */
  313. {
  314. if (virtual_list_view)
  315. {
  316. vlv_response.result = LDAP_UNWILLING_TO_PERFORM;
  317. vlv_make_response_control(pb, &vlv_response);
  318. }
  319. if (sort)
  320. {
  321. sort_make_sort_response_control(pb, LDAP_UNWILLING_TO_PERFORM, NULL);
  322. }
  323. sort = 0;
  324. virtual_list_view = 0;
  325. }
  326. }
  327. }
  328. /*
  329. * Get the base object for the search.
  330. * The entry "" will never be contained in the database,
  331. * so treat it as a special case.
  332. */
  333. if ( *base == '\0' )
  334. {
  335. e = NULL;
  336. }
  337. else
  338. {
  339. if ( ( e = find_entry( pb, be, addr, NULL )) == NULL )
  340. {
  341. /* error or referral sent by find_entry */
  342. return ldbm_back_search_cleanup(pb, li, sort_control, -1, NULL, 1, &basesdn, &vlv_request_control);
  343. }
  344. }
  345. /*
  346. * If this is a persistent search then the client is only
  347. * interested in entries that change, so we skip building
  348. * a candidate list.
  349. */
  350. if (operation_is_flag_set( operation, OP_FLAG_PS_CHANGESONLY ))
  351. {
  352. candidates = NULL;
  353. }
  354. else
  355. {
  356. time_t time_up= 0;
  357. int lookthrough_limit = 0;
  358. struct vlv_response vlv_response_control;
  359. int abandoned= 0;
  360. int vlv_rc;
  361. /*
  362. * Build a list of IDs for this entry and scope
  363. */
  364. if ((NULL != controls) && (sort) && (vlv)) {
  365. /* This candidate list is for vlv, no need for sort only. */
  366. switch (vlv_search_build_candidate_list(pb, &basesdn, &vlv_rc,
  367. sort_control,
  368. (vlv ? &vlv_request_control : NULL),
  369. &candidates, &vlv_response_control)) {
  370. case VLV_ACCESS_DENIED:
  371. return ldbm_back_search_cleanup(pb, li, sort_control,
  372. vlv_rc, "VLV Control",
  373. SLAPI_FAIL_GENERAL, &basesdn,
  374. &vlv_request_control);
  375. case VLV_BLD_LIST_FAILED:
  376. return ldbm_back_search_cleanup(pb, li, sort_control,
  377. vlv_response_control.result,
  378. NULL, SLAPI_FAIL_GENERAL,
  379. &basesdn, &vlv_request_control);
  380. case LDAP_SUCCESS:
  381. /* Log to the access log the particulars of this sort request */
  382. /* Log message looks like this: SORT <key list useful for input
  383. * to ldapsearch> <#candidates> | <unsortable> */
  384. sort_log_access(pb,sort_control,NULL);
  385. /* Since a pre-computed index was found for the VLV Search then
  386. * the candidate list now contains exactly what should be
  387. * returned.
  388. * There's no need to sort or trim the candidate list.
  389. *
  390. * However, the client will be expecting a Sort Response control
  391. */
  392. if (LDAP_SUCCESS !=
  393. sort_make_sort_response_control( pb, 0, NULL ) )
  394. {
  395. return ldbm_back_search_cleanup(pb, li, sort_control,
  396. LDAP_OPERATIONS_ERROR,
  397. "Sort Response Control",
  398. SLAPI_FAIL_GENERAL,
  399. &basesdn,
  400. &vlv_request_control);
  401. }
  402. }
  403. }
  404. if (candidates == NULL)
  405. {
  406. int rc = build_candidate_list(pb, be, e, base, scope,
  407. &lookup_returned_allids, &candidates);
  408. if (rc)
  409. {
  410. /* Error result sent by build_candidate_list */
  411. return ldbm_back_search_cleanup(pb, li, sort_control, -1,
  412. NULL, rc, &basesdn,
  413. &vlv_request_control);
  414. }
  415. /*
  416. * If we're sorting then we must check what administrative
  417. * limits should be imposed. Work out at what time to give
  418. * up, and how many entries we should sift through.
  419. */
  420. if (sort && (NULL != candidates))
  421. {
  422. time_t optime = 0;
  423. int tlimit = 0;
  424. slapi_pblock_get( pb, SLAPI_SEARCH_TIMELIMIT, &tlimit );
  425. slapi_pblock_get( pb, SLAPI_OPINITIATED_TIME, &optime );
  426. /*
  427. * (tlimit==-1) means no time limit
  428. */
  429. time_up = (tlimit==-1 ? -1 : optime + tlimit);
  430. lookthrough_limit = compute_lookthrough_limit( pb, li );
  431. }
  432. /*
  433. * If we're presenting a virtual list view, then apply the
  434. * search filter before sorting.
  435. */
  436. if (virtual_list_view && (NULL != candidates))
  437. {
  438. int r = 0;
  439. IDList *idl = NULL;
  440. Slapi_Filter *filter = NULL;
  441. slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, &filter );
  442. r = vlv_filter_candidates(be, pb, candidates, &basesdn,
  443. scope, filter, &idl,
  444. lookthrough_limit, time_up);
  445. if(r == 0)
  446. {
  447. idl_free(candidates);
  448. candidates= idl;
  449. }
  450. else
  451. {
  452. return ldbm_back_search_cleanup(pb, li, sort_control,
  453. r, NULL, -1, &basesdn,
  454. &vlv_request_control);
  455. }
  456. }
  457. /*
  458. * Client wants the server to sort the results.
  459. */
  460. if (sort)
  461. {
  462. if (NULL == candidates)
  463. {
  464. /* Even if candidates is NULL, we have to return a sort
  465. * response control with the LDAP_SUCCESS return code. */
  466. if (LDAP_SUCCESS !=
  467. sort_make_sort_response_control( pb, LDAP_SUCCESS, NULL ))
  468. {
  469. return ldbm_back_search_cleanup(pb, li, sort_control,
  470. (abandoned?-1:LDAP_PROTOCOL_ERROR),
  471. "Sort Response Control", -1,
  472. &basesdn, &vlv_request_control);
  473. }
  474. }
  475. else
  476. {
  477. /* Before we haste off to sort the candidates, we need to
  478. * prepare some information for the purpose of imposing the
  479. * administrative limits.
  480. * We figure out the time when the time limit will be up.
  481. * We can't use the size limit because we might be sorting
  482. * a candidate list larger than the result set.
  483. * But, we can use the lookthrough limit---we count each
  484. * time we access an entry as one look and act accordingly.
  485. */
  486. char *sort_error_type = NULL;
  487. int sort_return_value = 0;
  488. /* Don't log internal operations */
  489. if (!operation_is_flag_set(operation, OP_FLAG_INTERNAL)) {
  490. /* Log to the access log the particulars of this
  491. * sort request */
  492. /* Log message looks like this: SORT <key list useful for
  493. * input to ldapsearch> <#candidates> | <unsortable> */
  494. sort_log_access(pb,sort_control,candidates);
  495. }
  496. sort_return_value = sort_candidates( be, lookthrough_limit,
  497. time_up, pb, candidates,
  498. sort_control,
  499. &sort_error_type );
  500. /* Fix for bugid # 394184, SD, 20 Jul 00 */
  501. /* replace the hard coded return value by the appropriate
  502. * LDAP error code */
  503. switch (sort_return_value) {
  504. case LDAP_SUCCESS: /* Everything OK */
  505. vlv_response_control.result= LDAP_SUCCESS;
  506. break;
  507. case LDAP_PROTOCOL_ERROR: /* A protocol error */
  508. return ldbm_back_search_cleanup(pb, li, sort_control,
  509. LDAP_PROTOCOL_ERROR,
  510. "Sort Control", -1,
  511. &basesdn,
  512. &vlv_request_control);
  513. case LDAP_UNWILLING_TO_PERFORM: /* Too hard */
  514. case LDAP_OPERATIONS_ERROR: /* Operation error */
  515. case LDAP_TIMELIMIT_EXCEEDED: /* Timeout */
  516. vlv_response_control.result= LDAP_TIMELIMIT_EXCEEDED;
  517. break;
  518. case LDAP_ADMINLIMIT_EXCEEDED: /* Admin limit exceeded */
  519. vlv_response_control.result = LDAP_ADMINLIMIT_EXCEEDED;
  520. break;
  521. case LDAP_OTHER: /* Abandoned */
  522. abandoned = 1; /* So that we don't return a result code */
  523. is_sorting_critical = 1; /* In order to have the results
  524. discarded */
  525. break;
  526. default: /* Should never get here */
  527. break;
  528. }
  529. /* End fix for bug # 394184 */
  530. /*
  531. * If the sort control was marked as critical, and there was
  532. * an error in sorting, don't return any entries, and return
  533. * unavailableCriticalExtension in the searchResultDone message.
  534. */
  535. /* Fix for bugid #394184, SD, 05 Jul 00 */
  536. /* we were not actually returning unavailableCriticalExtension;
  537. now fixed (hopefully !) */
  538. if (is_sorting_critical && (0 != sort_return_value))
  539. {
  540. idl_free(candidates);
  541. candidates = idl_alloc(0);
  542. tmp_err = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
  543. tmp_desc = "Sort Response Control";
  544. }
  545. /* end Fix for bugid #394184 */
  546. /* Generate the control returned to the client to indicate
  547. * sort result */
  548. if (LDAP_SUCCESS != sort_make_sort_response_control( pb,
  549. sort_return_value, sort_error_type ) )
  550. {
  551. return ldbm_back_search_cleanup(pb, li, sort_control,
  552. (abandoned?-1:LDAP_PROTOCOL_ERROR),
  553. "Sort Response Control", -1,
  554. &basesdn, &vlv_request_control);
  555. }
  556. }
  557. }
  558. /*
  559. * If we're presenting a virtual list view, then the candidate list
  560. * must be trimmed down to just the range of entries requested.
  561. */
  562. if (virtual_list_view)
  563. {
  564. if (NULL != candidates && candidates->b_nids>0)
  565. {
  566. IDList *idl= NULL;
  567. vlv_response_control.result =
  568. vlv_trim_candidates(be, candidates, sort_control,
  569. &vlv_request_control, &idl, &vlv_response_control);
  570. if(vlv_response_control.result==0)
  571. {
  572. idl_free(candidates);
  573. candidates = idl;
  574. }
  575. else
  576. {
  577. return ldbm_back_search_cleanup(pb, li, sort_control,
  578. vlv_response_control.result,
  579. NULL, -1, &basesdn,
  580. &vlv_request_control);
  581. }
  582. }
  583. else
  584. {
  585. vlv_response_control.targetPosition = 0;
  586. vlv_response_control.contentCount = 0;
  587. vlv_response_control.result = LDAP_SUCCESS;
  588. }
  589. }
  590. }
  591. if (virtual_list_view)
  592. {
  593. if(LDAP_SUCCESS !=
  594. vlv_make_response_control( pb, &vlv_response_control ))
  595. {
  596. return ldbm_back_search_cleanup(pb, li, sort_control,
  597. (abandoned?-1:LDAP_PROTOCOL_ERROR),
  598. "VLV Response Control", -1,
  599. &basesdn, &vlv_request_control);
  600. }
  601. /* Log the VLV operation */
  602. vlv_print_access_log(pb,&vlv_request_control,&vlv_response_control);
  603. }
  604. }
  605. cache_return( &inst->inst_cache, &e );
  606. /*
  607. * if the candidate list is an allids list, arrange for access log
  608. * to record that fact.
  609. */
  610. if ( NULL != candidates && ALLIDS( candidates )) {
  611. unsigned int opnote = SLAPI_OP_NOTE_UNINDEXED;
  612. int ri = 0;
  613. /*
  614. * Return error if nsslapd-require-index is set and
  615. * this is not an internal operation.
  616. * We hope the plugins know what they are doing!
  617. */
  618. if (!operation_is_flag_set(operation, OP_FLAG_INTERNAL)) {
  619. PR_Lock(inst->inst_config_mutex);
  620. ri = inst->require_index;
  621. PR_Unlock(inst->inst_config_mutex);
  622. if (ri) {
  623. idl_free(candidates);
  624. candidates = idl_alloc(0);
  625. tmp_err = LDAP_UNWILLING_TO_PERFORM;
  626. tmp_desc = "Search is not indexed";
  627. }
  628. }
  629. slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote );
  630. }
  631. sr->sr_candidates = candidates;
  632. sr->sr_virtuallistview = virtual_list_view;
  633. /* check to see if we can skip the filter test */
  634. if ( li->li_filter_bypass && NULL != candidates && !virtual_list_view
  635. && !lookup_returned_allids ) {
  636. Slapi_Filter *filter = NULL;
  637. slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, &filter );
  638. if ( can_skip_filter_test( pb, filter, scope, candidates)) {
  639. sr->sr_flags |= SR_FLAG_CAN_SKIP_FILTER_TEST;
  640. }
  641. }
  642. /* Fix for bugid #394184, SD, 05 Jul 00 */
  643. /* tmp_err == -1: no error */
  644. return ldbm_back_search_cleanup(pb, li, sort_control, tmp_err, tmp_desc,
  645. (tmp_err == -1 ? 0 : -1), &basesdn,
  646. &vlv_request_control);
  647. /* end Fix for bugid #394184 */
  648. }
  649. /*
  650. * Build a candidate list for this backentry and scope.
  651. * Could be a BASE, ONELEVEL, or SUBTREE search.
  652. *
  653. * Returns:
  654. * 0 - success
  655. * <0 - fail
  656. *
  657. */
  658. static int
  659. build_candidate_list( Slapi_PBlock *pb, backend *be, struct backentry *e,
  660. const char * base, int scope, int *lookup_returned_allidsp,
  661. IDList** candidates)
  662. {
  663. struct ldbminfo *li = (struct ldbminfo *) be->be_database->plg_private;
  664. int managedsait= 0;
  665. Slapi_Filter *filter= NULL;
  666. int err= 0;
  667. int r= 0;
  668. slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, &filter );
  669. slapi_pblock_get( pb, SLAPI_MANAGEDSAIT, &managedsait );
  670. switch ( scope ) {
  671. case LDAP_SCOPE_BASE:
  672. *candidates = base_candidates( pb, e );
  673. break;
  674. case LDAP_SCOPE_ONELEVEL:
  675. *candidates = onelevel_candidates( pb, be, base, e, filter, managedsait,
  676. lookup_returned_allidsp, &err );
  677. break;
  678. case LDAP_SCOPE_SUBTREE:
  679. *candidates = subtree_candidates(pb, be, base, e, filter, managedsait,
  680. lookup_returned_allidsp, &err);
  681. break;
  682. default:
  683. slapi_send_ldap_result( pb, LDAP_PROTOCOL_ERROR, NULL, "Bad scope", 0, NULL );
  684. r = SLAPI_FAIL_GENERAL;
  685. }
  686. if ( 0 != err && DB_NOTFOUND != err ) {
  687. LDAPDebug( LDAP_DEBUG_ANY, "database error %d\n", err, 0, 0 );
  688. slapi_send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL, NULL,
  689. 0, NULL );
  690. if (LDBM_OS_ERR_IS_DISKFULL(err)) r = return_on_disk_full(li);
  691. else r = SLAPI_FAIL_GENERAL;
  692. }
  693. /*
  694. * If requested, set a flag to indicate whether the indexed
  695. * lookup returned an ALLIDs block. Note that this is taken care of
  696. * above already for subtree searches.
  697. */
  698. if ( NULL != lookup_returned_allidsp ) {
  699. if ( 0 == err || DB_NOTFOUND == err ) {
  700. if ( !(*lookup_returned_allidsp) && LDAP_SCOPE_SUBTREE != scope ) {
  701. *lookup_returned_allidsp =
  702. ( NULL != *candidates && ALLIDS( *candidates ));
  703. }
  704. } else {
  705. *lookup_returned_allidsp = 0;
  706. }
  707. }
  708. LDAPDebug(LDAP_DEBUG_TRACE, "candidate list has %lu ids\n",
  709. *candidates ? (*candidates)->b_nids : 0L, 0, 0);
  710. return r;
  711. }
  712. /*
  713. * Build a candidate list for a BASE scope search.
  714. */
  715. static IDList *
  716. base_candidates(Slapi_PBlock *pb, struct backentry *e)
  717. {
  718. IDList *idl= idl_alloc( 1 );
  719. idl_append( idl, NULL == e ? 0 : e->ep_id );
  720. return( idl );
  721. }
  722. /*
  723. * Modify the filter to include entries of the referral objectclass
  724. *
  725. * make (|(originalfilter)(objectclass=referral))
  726. *
  727. * "focref, forr" are temporary filters which the caller must free
  728. * non-recursively when done with the returned filter.
  729. */
  730. static Slapi_Filter*
  731. create_referral_filter(Slapi_Filter* filter, Slapi_Filter** focref, Slapi_Filter** forr)
  732. {
  733. char *buf = slapi_ch_strdup( "objectclass=referral" );
  734. *focref = slapi_str2filter( buf );
  735. *forr = slapi_filter_join( LDAP_FILTER_OR, filter, *focref );
  736. slapi_ch_free((void **)&buf);
  737. return *forr;
  738. }
  739. /*
  740. * Modify the filter to be a one level search.
  741. *
  742. * (&(parentid=idofbase)(|(originalfilter)(objectclass=referral)))
  743. *
  744. * "fid2kids, focref, fand, forr" are temporary filters which the
  745. * caller must free'd non-recursively when done with the returned filter.
  746. *
  747. * This function is exported for the VLV code to use.
  748. */
  749. Slapi_Filter*
  750. create_onelevel_filter(Slapi_Filter* filter, const struct backentry *baseEntry, int managedsait, Slapi_Filter** fid2kids, Slapi_Filter** focref, Slapi_Filter** fand, Slapi_Filter** forr)
  751. {
  752. Slapi_Filter *ftop= filter;
  753. char buf[40];
  754. if ( !managedsait )
  755. {
  756. ftop= create_referral_filter(filter, focref, forr);
  757. }
  758. sprintf( buf, "parentid=%lu", (u_long)(baseEntry != NULL ? baseEntry->ep_id : 0) );
  759. *fid2kids = slapi_str2filter( buf );
  760. *fand = slapi_filter_join( LDAP_FILTER_AND, ftop, *fid2kids );
  761. return *fand;
  762. }
  763. /*
  764. * Build a candidate list for a ONELEVEL scope search.
  765. */
  766. static IDList *
  767. onelevel_candidates(
  768. Slapi_PBlock *pb,
  769. backend *be,
  770. const char *base,
  771. struct backentry *e,
  772. Slapi_Filter *filter,
  773. int managedsait,
  774. int *lookup_returned_allidsp,
  775. int *err
  776. )
  777. {
  778. Slapi_Filter *fid2kids= NULL;
  779. Slapi_Filter *focref= NULL;
  780. Slapi_Filter *fand= NULL;
  781. Slapi_Filter *forr= NULL;
  782. Slapi_Filter *ftop= NULL;
  783. IDList *candidates;
  784. /*
  785. * modify the filter to be something like this:
  786. *
  787. * (&(parentid=idofbase)(|(originalfilter)(objectclass=referral)))
  788. */
  789. ftop= create_onelevel_filter(filter, e, managedsait, &fid2kids, &focref, &fand, &forr);
  790. /* from here, it's just like subtree_candidates */
  791. candidates = filter_candidates( pb, be, base, ftop, NULL, 0, err );
  792. *lookup_returned_allidsp = slapi_be_is_flag_set(be, SLAPI_BE_FLAG_DONT_BYPASS_FILTERTEST);
  793. /* free up just the filter stuff we allocated above */
  794. slapi_filter_free( fid2kids, 0 );
  795. slapi_filter_free( fand, 0 );
  796. slapi_filter_free( forr, 0 );
  797. slapi_filter_free( focref, 0 );
  798. return( candidates );
  799. }
  800. /*
  801. * We need to modify the filter to be something like this:
  802. *
  803. * (|(originalfilter)(objectclass=referral))
  804. *
  805. * the "objectclass=referral" part is used to select referrals to return.
  806. * it is only included if the managedsait service control is not set.
  807. *
  808. * This function is exported for the VLV code to use.
  809. */
  810. Slapi_Filter*
  811. create_subtree_filter(Slapi_Filter* filter, int managedsait, Slapi_Filter** focref, Slapi_Filter** forr)
  812. {
  813. Slapi_Filter *ftop= filter;
  814. if ( !managedsait )
  815. {
  816. ftop= create_referral_filter(filter, focref, forr);
  817. }
  818. return ftop;
  819. }
  820. /*
  821. * Build a candidate list for a SUBTREE scope search.
  822. */
  823. IDList *
  824. subtree_candidates(
  825. Slapi_PBlock *pb,
  826. backend *be,
  827. const char *base,
  828. const struct backentry *e,
  829. Slapi_Filter *filter,
  830. int managedsait,
  831. int *allids_before_scopingp,
  832. int *err
  833. )
  834. {
  835. Slapi_Filter *focref= NULL;
  836. Slapi_Filter *forr= NULL;
  837. Slapi_Filter *ftop= NULL;
  838. IDList *candidates;
  839. PRBool has_tombstone_filter;
  840. int isroot = 0;
  841. /* make (|(originalfilter)(objectclass=referral)) */
  842. ftop= create_subtree_filter(filter, managedsait, &focref, &forr);
  843. /* Fetch a candidate list for the original filter */
  844. candidates = filter_candidates( pb, be, base, ftop, NULL, 0, err );
  845. slapi_filter_free( forr, 0 );
  846. slapi_filter_free( focref, 0 );
  847. /* set 'allids before scoping' flag */
  848. if ( NULL != allids_before_scopingp ) {
  849. *allids_before_scopingp = ( NULL != candidates && ALLIDS( candidates ));
  850. }
  851. has_tombstone_filter = (filter->f_flags & SLAPI_FILTER_TOMBSTONE);
  852. slapi_pblock_get( pb, SLAPI_REQUESTOR_ISROOT, &isroot );
  853. /*
  854. * Apply the DN components if the candidate list is greater than
  855. * our threshold, and if the filter is not "(objectclass=nstombstone)",
  856. * since tombstone entries are not indexed in the ancestorid index.
  857. */
  858. if(candidates!=NULL && ( idl_length(candidates)>FILTER_TEST_THRESHOLD) && !has_tombstone_filter)
  859. {
  860. IDList *tmp = candidates, *descendants = NULL;
  861. *err = ldbm_ancestorid_read(be, NULL, e->ep_id, &descendants);
  862. idl_insert(&descendants, e->ep_id);
  863. candidates = idl_intersection(be, candidates, descendants);
  864. idl_free(tmp);
  865. idl_free(descendants);
  866. }
  867. return( candidates );
  868. }
  869. static int grok_filter(struct slapi_filter *f);
  870. #if 0
  871. /* Helper for grok_filter() */
  872. static int
  873. grok_filter_list(struct slapi_filter *flist)
  874. {
  875. struct slapi_filter *f;
  876. /* Scan the clauses of the AND filter, if any of them fails the grok, then we fail */
  877. for ( f = flist; f != NULL; f = f->f_next ) {
  878. if ( !grok_filter(f) ) {
  879. return( 0 );
  880. }
  881. }
  882. return( 1 );
  883. }
  884. #endif
  885. /* Helper function for can_skip_filter_test() */
  886. static int grok_filter(struct slapi_filter *f)
  887. {
  888. switch ( f->f_choice ) {
  889. case LDAP_FILTER_EQUALITY:
  890. return 1; /* If there's an ID list and an equality filter, we can skip the filter test */
  891. case LDAP_FILTER_SUBSTRINGS:
  892. return 0;
  893. case LDAP_FILTER_GE:
  894. return 1;
  895. case LDAP_FILTER_LE:
  896. return 1;
  897. case LDAP_FILTER_PRESENT:
  898. return 1; /* If there's an ID list, and a presence filter, we can skip the filter test */
  899. case LDAP_FILTER_APPROX:
  900. return 0;
  901. case LDAP_FILTER_EXTENDED:
  902. return 0;
  903. case LDAP_FILTER_AND:
  904. return 0; /* Unless we check to see whether the presence and equality branches
  905. of the search filter were all indexed, we get things wrong here,
  906. so let's punt for now */
  907. /* return grok_filter_list(f->f_and); AND clauses are potentially OK */
  908. case LDAP_FILTER_OR:
  909. return 0;
  910. case LDAP_FILTER_NOT:
  911. return 0;
  912. default:
  913. return 0;
  914. }
  915. }
  916. /* Routine which says whether or not the indices produced a "correct" answer */
  917. static int
  918. can_skip_filter_test(
  919. Slapi_PBlock *pb,
  920. struct slapi_filter *f,
  921. int scope,
  922. IDList *idl
  923. )
  924. {
  925. int rc = 0;
  926. /* Is the ID list ALLIDS ? */
  927. if ( ALLIDS(idl)) {
  928. /* If so, then can't optimize */
  929. return rc;
  930. }
  931. /* Is this a base scope search? */
  932. if ( scope == LDAP_SCOPE_BASE ) {
  933. /*
  934. * If so, then we can't optimize. Why not? Because we only consult
  935. * the entrydn index in producing our 1 candidate, and that means
  936. * we have not used the filter to produce the candidate list.
  937. */
  938. return rc;
  939. }
  940. /* Grok the filter and tell me if it has only equality components in it */
  941. rc = grok_filter(f);
  942. /* If we haven't determined that we can't skip the filter test already,
  943. * do one last check for attribute subtypes. We don't need to worry
  944. * about any complex filters here since grok_filter() will have already
  945. * assumed that we can't skip the filter test in those cases. */
  946. if (rc != 0) {
  947. char *type = NULL;
  948. char *basetype = NULL;
  949. /* We don't need to free type since that's taken
  950. * care of when the filter is free'd later. We
  951. * do need to free basetype when we are done. */
  952. slapi_filter_get_attribute_type(f, &type);
  953. basetype = slapi_attr_basetype(type, NULL, 0);
  954. /* Is the filter using an attribute subtype? */
  955. if (strcasecmp(type, basetype) != 0) {
  956. /* If so, we can't optimize since attribute subtypes
  957. * are simply indexed under their basetype attribute.
  958. * The basetype index has no knowledge of the subtype
  959. * itself. In the future, we should add support for
  960. * indexing the subtypes so we can optimize this type
  961. * of search. */
  962. rc = 0;
  963. }
  964. slapi_ch_free_string(&basetype);
  965. }
  966. return rc;
  967. }
  968. /*
  969. * Return the next entry in the result set. The entry is returned
  970. * in the pblock.
  971. * Returns 0 normally. If -1 is returned, it means that some
  972. * exceptional condition, e.g. timelimit exceeded has occurred,
  973. * and this routine has sent a result to the client. If zero
  974. * is returned and no entry is available in the PBlock, then
  975. * we've iterated through all the entries.
  976. */
  977. int
  978. ldbm_back_next_search_entry( Slapi_PBlock *pb )
  979. {
  980. return ldbm_back_next_search_entry_ext( pb, 0 );
  981. }
  982. int
  983. ldbm_back_next_search_entry_ext( Slapi_PBlock *pb, int use_extension )
  984. {
  985. backend *be;
  986. ldbm_instance *inst;
  987. struct ldbminfo *li;
  988. int scope;
  989. int managedsait;
  990. Slapi_Attr *attr;
  991. Slapi_Filter *filter;
  992. char *base;
  993. back_search_result_set *sr;
  994. ID id;
  995. struct backentry *e;
  996. int nentries;
  997. time_t curtime, stoptime, optime;
  998. int tlimit, llimit, slimit, isroot;
  999. struct berval **urls = NULL;
  1000. int err;
  1001. Slapi_DN basesdn;
  1002. char *target_uniqueid;
  1003. int rc = 0;
  1004. slapi_pblock_get( pb, SLAPI_BACKEND, &be );
  1005. slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
  1006. slapi_pblock_get( pb, SLAPI_SEARCH_SCOPE, &scope );
  1007. slapi_pblock_get( pb, SLAPI_MANAGEDSAIT, &managedsait );
  1008. slapi_pblock_get( pb, SLAPI_SEARCH_FILTER, &filter );
  1009. slapi_pblock_get( pb, SLAPI_SEARCH_TARGET, &base );
  1010. slapi_pblock_get( pb, SLAPI_NENTRIES, &nentries );
  1011. slapi_pblock_get( pb, SLAPI_SEARCH_SIZELIMIT, &slimit );
  1012. slapi_pblock_get( pb, SLAPI_SEARCH_TIMELIMIT, &tlimit );
  1013. slapi_pblock_get( pb, SLAPI_OPINITIATED_TIME, &optime );
  1014. slapi_pblock_get( pb, SLAPI_REQUESTOR_ISROOT, &isroot );
  1015. slapi_pblock_get( pb, SLAPI_SEARCH_REFERRALS, &urls );
  1016. slapi_pblock_get( pb, SLAPI_SEARCH_RESULT_SET, &sr );
  1017. slapi_pblock_get( pb, SLAPI_TARGET_UNIQUEID, &target_uniqueid );
  1018. if (sr->sr_current_sizelimit >= 0) {
  1019. /*
  1020. * sr_current_sizelimit contains the current sizelimit.
  1021. * In case of paged results, getting one page is one operation,
  1022. * while the results on each page are from same back_search_result_set.
  1023. * To maintain sizelimit beyond operations, back_search_result_set
  1024. * holds the current sizelimit value.
  1025. * (The current sizelimit is valid inside an operation, as well.)
  1026. */
  1027. slimit = sr->sr_current_sizelimit;
  1028. }
  1029. inst = (ldbm_instance *) be->be_instance_info;
  1030. slapi_sdn_init_dn_ndn_byref(&basesdn,base); /* normalized by front end */
  1031. /* Return to the cache the entry we handed out last time */
  1032. /* If we are using the extension, the front end will tell
  1033. * us when to do this so we don't do it now */
  1034. if ( !use_extension )
  1035. {
  1036. cache_return( &inst->inst_cache, &(sr->sr_entry) );
  1037. }
  1038. if(sr->sr_vlventry != NULL && !use_extension )
  1039. {
  1040. /* This empty entry was handed out last time because the ACL check failed on a VLV Search. */
  1041. /* The empty entry has a pointer to the cache entry dn... make sure we don't free the dn */
  1042. /* which belongs to the cache entry. */
  1043. slapi_entry_free( sr->sr_vlventry );
  1044. sr->sr_vlventry = NULL;
  1045. }
  1046. stoptime = optime + tlimit;
  1047. llimit = sr->sr_lookthroughlimit;
  1048. /* Find the next candidate entry and return it. */
  1049. while ( 1 )
  1050. {
  1051. /* check for abandon */
  1052. if ( slapi_op_abandoned( pb ))
  1053. {
  1054. /* in case paged results, clean up the conn */
  1055. pagedresults_set_search_result(pb->pb_conn, NULL);
  1056. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL );
  1057. if ( use_extension ) {
  1058. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY_EXT, NULL );
  1059. }
  1060. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, NULL );
  1061. delete_search_result_set( &sr );
  1062. rc = SLAPI_FAIL_GENERAL;
  1063. goto bail;
  1064. }
  1065. /* check time limit */
  1066. curtime = current_time();
  1067. if ( tlimit != -1 && curtime > stoptime )
  1068. {
  1069. slapi_send_ldap_result( pb, LDAP_TIMELIMIT_EXCEEDED, NULL, NULL, nentries, urls );
  1070. /* in case paged results, clean up the conn */
  1071. pagedresults_set_search_result(pb->pb_conn, NULL);
  1072. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL );
  1073. if ( use_extension ) {
  1074. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY_EXT, NULL );
  1075. }
  1076. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, NULL );
  1077. delete_search_result_set( &sr );
  1078. rc = SLAPI_FAIL_GENERAL;
  1079. goto bail;
  1080. }
  1081. /* check lookthrough limit */
  1082. if ( llimit != -1 && sr->sr_lookthroughcount >= llimit )
  1083. {
  1084. slapi_send_ldap_result( pb, LDAP_ADMINLIMIT_EXCEEDED, NULL, NULL, nentries, urls );
  1085. /* in case paged results, clean up the conn */
  1086. pagedresults_set_search_result(pb->pb_conn, NULL);
  1087. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL );
  1088. if ( use_extension ) {
  1089. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY_EXT, NULL );
  1090. }
  1091. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, NULL );
  1092. delete_search_result_set( &sr );
  1093. rc = SLAPI_FAIL_GENERAL;
  1094. goto bail;
  1095. }
  1096. /* get the entry */
  1097. id = idl_iterator_dereference_increment(&(sr->sr_current), sr->sr_candidates);
  1098. if ( id == NOID )
  1099. {
  1100. /* No more entries */
  1101. /* destroy back_search_result_set */
  1102. /* in case paged results, clean up the conn */
  1103. pagedresults_set_search_result(pb->pb_conn, NULL);
  1104. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL );
  1105. if ( use_extension ) {
  1106. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY_EXT, NULL );
  1107. }
  1108. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, NULL );
  1109. delete_search_result_set( &sr );
  1110. rc = 0;
  1111. goto bail;
  1112. }
  1113. ++sr->sr_lookthroughcount; /* checked above */
  1114. /* get the entry */
  1115. if ( (e = id2entry( be, id, NULL, &err )) == NULL )
  1116. {
  1117. if ( err != 0 && err != DB_NOTFOUND )
  1118. {
  1119. LDAPDebug( LDAP_DEBUG_ANY, "next_search_entry db err %d\n", err, 0, 0 );
  1120. if (LDBM_OS_ERR_IS_DISKFULL(err))
  1121. {
  1122. /* disk full in the middle of returning search results
  1123. * is gonna be traumatic. unavoidable.
  1124. */
  1125. slapi_send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL);
  1126. rc = return_on_disk_full(li);
  1127. goto bail;
  1128. }
  1129. }
  1130. LDAPDebug( LDAP_DEBUG_ARGS, "candidate %lu not found\n", (u_long)id, 0, 0 );
  1131. if ( err == DB_NOTFOUND )
  1132. {
  1133. /* Since we didn't really look at this entry, we should
  1134. * decrement the lookthrough counter (it was just incremented).
  1135. * If we didn't do this, it would be possible to go over the
  1136. * lookthrough limit when there are fewer entries in the database
  1137. * than the lookthrough limit. This could happen on an ALLIDS
  1138. * search after adding a bunch of entries and then deleting
  1139. * them. */
  1140. --sr->sr_lookthroughcount;
  1141. }
  1142. continue;
  1143. }
  1144. e->ep_vlventry = NULL;
  1145. sr->sr_entry = e;
  1146. /*
  1147. * If it's a referral, return it without checking the
  1148. * filter explicitly here since it's only a candidate anyway. Do
  1149. * check the scope though.
  1150. */
  1151. if ( !managedsait && slapi_entry_attr_find( e->ep_entry, "ref", &attr ) == 0)
  1152. {
  1153. Slapi_Value **refs= attr_get_present_values(attr);
  1154. if ( refs == NULL || refs[0] == NULL )
  1155. {
  1156. char ebuf[ BUFSIZ ];
  1157. LDAPDebug( LDAP_DEBUG_ANY, "null ref in (%s)\n", escape_string( backentry_get_ndn(e), ebuf ), 0, 0 );
  1158. }
  1159. else if ( slapi_sdn_scope_test( backentry_get_sdn(e), &basesdn, scope ))
  1160. {
  1161. if ( use_extension ) {
  1162. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY_EXT, e );
  1163. }
  1164. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, e->ep_entry );
  1165. rc = 0;
  1166. goto bail;
  1167. }
  1168. }
  1169. else
  1170. {
  1171. /*
  1172. * As per slapi_filter_test:
  1173. * 0 filter matched
  1174. * -1 filter did not match
  1175. * >0 an ldap error code
  1176. */
  1177. int filter_test = -1;
  1178. if((slapi_entry_flag_is_set(e->ep_entry,SLAPI_ENTRY_LDAPSUBENTRY)
  1179. && !filter_flag_is_set(filter,SLAPI_FILTER_LDAPSUBENTRY)) ||
  1180. (slapi_entry_flag_is_set(e->ep_entry,SLAPI_ENTRY_FLAG_TOMBSTONE)
  1181. && ((!isroot && !filter_flag_is_set(filter, SLAPI_FILTER_RUV)) ||
  1182. !filter_flag_is_set(filter, SLAPI_FILTER_TOMBSTONE))))
  1183. {
  1184. /* If the entry is an LDAP subentry and filter don't filter subentries OR
  1185. * the entry is a TombStone and filter don't filter Tombstone
  1186. * don't return the entry. We make a special case to allow a non-root user
  1187. * to search for the RUV entry using a filter of:
  1188. *
  1189. * "(&(objectclass=nstombstone)(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff))"
  1190. *
  1191. * For this RUV case, we let the ACL check apply.
  1192. */
  1193. /* ugaston - we don't want to mistake this filter failure with the one below due to ACL,
  1194. * because whereas the former should be read as 'no entry must be returned', the latter
  1195. * might still lead to return an empty entry. */
  1196. filter_test=-1;
  1197. }
  1198. else
  1199. {
  1200. /* it's a regular entry, check if it matches the filter, and passes the ACL check */
  1201. if ( 0 != ( sr->sr_flags & SR_FLAG_CAN_SKIP_FILTER_TEST )) {
  1202. /* Since we do access control checking in the filter test (?Why?) we need to check access now */
  1203. LDAPDebug( LDAP_DEBUG_FILTER, "Bypassing filter test\n", 0, 0, 0 );
  1204. if ( ACL_CHECK_FLAG ) {
  1205. filter_test = slapi_vattr_filter_test_ext( pb, e->ep_entry, filter, ACL_CHECK_FLAG, 1 /* Only perform access checking, thank you */);
  1206. } else {
  1207. filter_test = 0;
  1208. }
  1209. if (li->li_filter_bypass_check) {
  1210. int ft_rc;
  1211. LDAPDebug( LDAP_DEBUG_FILTER, "Checking bypass\n", 0, 0, 0 );
  1212. ft_rc = slapi_vattr_filter_test( pb, e->ep_entry, filter,
  1213. ACL_CHECK_FLAG );
  1214. if (filter_test != ft_rc) {
  1215. /* Oops ! This means that we thought we could bypass the filter test, but noooo... */
  1216. char ebuf[ BUFSIZ ];
  1217. LDAPDebug( LDAP_DEBUG_ANY, "Filter bypass ERROR on entry %s\n", escape_string( backentry_get_ndn(e), ebuf ), 0, 0 );
  1218. filter_test = ft_rc; /* Fix the error */
  1219. }
  1220. }
  1221. } else {
  1222. /* Old-style case---we need to do a filter test */
  1223. filter_test = slapi_vattr_filter_test( pb, e->ep_entry, filter, ACL_CHECK_FLAG);
  1224. }
  1225. }
  1226. if ( (filter_test == 0) || (sr->sr_virtuallistview && (filter_test != -1)) )
  1227. /* ugaston - if filter failed due to subentries or tombstones (filter_test=-1),
  1228. * just forget about it, since we don't want to return anything at all. */
  1229. {
  1230. if ( slapi_uniqueIDCompareString(target_uniqueid, e->ep_entry->e_uniqueid) ||
  1231. slapi_sdn_scope_test( backentry_get_sdn(e), &basesdn, scope ))
  1232. {
  1233. /* check size limit */
  1234. if ( slimit >= 0 )
  1235. {
  1236. if ( --slimit < 0 ) {
  1237. cache_return( &inst->inst_cache, &e );
  1238. /* in case paged results, clean up the conn */
  1239. pagedresults_set_search_result(pb->pb_conn, NULL);
  1240. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL );
  1241. delete_search_result_set( &sr );
  1242. slapi_send_ldap_result( pb, LDAP_SIZELIMIT_EXCEEDED, NULL, NULL, nentries, urls );
  1243. rc = SLAPI_FAIL_GENERAL;
  1244. goto bail;
  1245. }
  1246. slapi_pblock_set( pb, SLAPI_SEARCH_SIZELIMIT, &slimit );
  1247. sr->sr_current_sizelimit = slimit;
  1248. }
  1249. if ( (filter_test != 0) && sr->sr_virtuallistview)
  1250. {
  1251. /* Slapi Filter Test failed.
  1252. * Must be that the ACL check failed.
  1253. * Send back an empty entry.
  1254. */
  1255. sr->sr_vlventry = slapi_entry_alloc();
  1256. slapi_entry_init(sr->sr_vlventry,slapi_ch_strdup(slapi_entry_get_dn_const(e->ep_entry)),NULL);
  1257. e->ep_vlventry = sr->sr_vlventry;
  1258. if ( use_extension ) {
  1259. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY_EXT, e );
  1260. }
  1261. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, sr->sr_vlventry );
  1262. } else {
  1263. if ( use_extension ) {
  1264. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY_EXT, e );
  1265. }
  1266. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_ENTRY, e->ep_entry );
  1267. }
  1268. rc = 0;
  1269. goto bail;
  1270. }
  1271. else
  1272. {
  1273. cache_return ( &inst->inst_cache, &(sr->sr_entry) );
  1274. }
  1275. }
  1276. else
  1277. {
  1278. /* Failed the filter test, and this isn't a VLV Search */
  1279. cache_return( &inst->inst_cache, &(sr->sr_entry) );
  1280. if (LDAP_UNWILLING_TO_PERFORM == filter_test) {
  1281. /* Need to catch this error to detect the vattr loop */
  1282. slapi_send_ldap_result( pb, filter_test, NULL,
  1283. "Failed the filter test", 0, NULL );
  1284. rc = SLAPI_FAIL_GENERAL;
  1285. goto bail;
  1286. } else if (LDAP_TIMELIMIT_EXCEEDED == filter_test) {
  1287. slapi_send_ldap_result( pb, LDAP_TIMELIMIT_EXCEEDED, NULL, NULL, nentries, urls );
  1288. rc = SLAPI_FAIL_GENERAL;
  1289. goto bail;
  1290. }
  1291. }
  1292. }
  1293. }
  1294. bail:
  1295. slapi_sdn_done(&basesdn);
  1296. return rc;
  1297. }
  1298. /*
  1299. * Move back the current position in the search result set by one.
  1300. * Paged Results needs to read ahead one entry to catch the end of the search
  1301. * result set at the last entry not to show the prompt when there is no more
  1302. * entries.
  1303. */
  1304. void
  1305. ldbm_back_prev_search_results( Slapi_PBlock *pb )
  1306. {
  1307. back_search_result_set *sr;
  1308. slapi_pblock_get( pb, SLAPI_SEARCH_RESULT_SET, &sr );
  1309. if (sr) {
  1310. idl_iterator_decrement(&(sr->sr_current));
  1311. }
  1312. return;
  1313. }
  1314. static back_search_result_set*
  1315. new_search_result_set(IDList *idl, int vlv, int lookthroughlimit)
  1316. {
  1317. back_search_result_set *p = (back_search_result_set *)slapi_ch_calloc( 1, sizeof( back_search_result_set ));
  1318. p->sr_candidates = idl;
  1319. p->sr_current = idl_iterator_init(idl);
  1320. p->sr_lookthroughlimit = lookthroughlimit;
  1321. p->sr_virtuallistview = vlv;
  1322. p->sr_current_sizelimit = -1;
  1323. return p;
  1324. }
  1325. static void
  1326. delete_search_result_set( back_search_result_set **sr )
  1327. {
  1328. if ( NULL == sr || NULL == *sr)
  1329. {
  1330. return;
  1331. }
  1332. if ( NULL != (*sr)->sr_candidates )
  1333. {
  1334. idl_free( (*sr)->sr_candidates );
  1335. }
  1336. slapi_ch_free( (void**)sr );
  1337. }
  1338. void
  1339. ldbm_back_search_results_release( void **sr )
  1340. {
  1341. delete_search_result_set( (back_search_result_set **)sr );
  1342. }
  1343. int
  1344. ldbm_back_entry_release( Slapi_PBlock *pb, void *backend_info_ptr ) {
  1345. backend *be;
  1346. ldbm_instance *inst;
  1347. if ( backend_info_ptr == NULL )
  1348. return 1;
  1349. slapi_pblock_get( pb, SLAPI_BACKEND, &be );
  1350. inst = (ldbm_instance *) be->be_instance_info;
  1351. cache_return( &inst->inst_cache, (struct backentry **)&backend_info_ptr );
  1352. if( ((struct backentry *) backend_info_ptr)->ep_vlventry != NULL )
  1353. {
  1354. /* This entry was created during a vlv search whose acl check failed. It needs to be
  1355. * freed here */
  1356. slapi_entry_free( ((struct backentry *) backend_info_ptr)->ep_vlventry );
  1357. ((struct backentry *) backend_info_ptr)->ep_vlventry = NULL;
  1358. }
  1359. return 0;
  1360. }