ldbm_search.c 77 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. #include <config.h>
  11. #endif
  12. /* search.c - ldbm backend search function */
  13. /* view with ts=4 */
  14. #include <ldap.h>
  15. #include "back-ldbm.h"
  16. #include "vlv_srch.h"
  17. /*
  18. * Used for ldap_result passed to ldbm_back_search_cleanup.
  19. * If (ldap_result == LDBM_SRCH_DEFAULT_RESULT) || (ldap_result == LDAP_SUCCESS),
  20. * don't call slapi_send_ldap_result.
  21. * Note: openldap result codes could be negative values. OL (-1) is LDAP_SERVER_DOWN.
  22. * Thus, it's safe to borrow the value here.
  23. */
  24. #define LDBM_SRCH_DEFAULT_RESULT (-1)
  25. /* prototypes */
  26. static int build_candidate_list(Slapi_PBlock *pb, backend *be, struct backentry *e, const char *base, int scope, int *lookup_returned_allidsp, IDList **candidates);
  27. static IDList *base_candidates(Slapi_PBlock *pb, struct backentry *e);
  28. 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);
  29. static back_search_result_set *new_search_result_set(IDList *idl, int vlv, int lookthroughlimit);
  30. static void delete_search_result_set(Slapi_PBlock *pb, back_search_result_set **sr);
  31. static int can_skip_filter_test(Slapi_PBlock *pb, struct slapi_filter *f, int scope, IDList *idl);
  32. /* This is for performance testing, allows us to disable ACL checking altogether */
  33. #if defined(DISABLE_ACL_CHECK)
  34. #define ACL_CHECK_FLAG 0
  35. #else
  36. #define ACL_CHECK_FLAG 1
  37. #endif
  38. #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)
  39. int
  40. compute_lookthrough_limit(Slapi_PBlock *pb, struct ldbminfo *li)
  41. {
  42. Slapi_Connection *conn = NULL;
  43. int limit;
  44. Slapi_Operation *op;
  45. int isroot = 0;
  46. slapi_pblock_get(pb, SLAPI_REQUESTOR_ISROOT, &isroot);
  47. slapi_pblock_get(pb, SLAPI_CONNECTION, &conn);
  48. slapi_pblock_get(pb, SLAPI_OPERATION, &op);
  49. if (isroot) {
  50. limit = -1;
  51. } else {
  52. if (op_is_pagedresults(op)) {
  53. if (slapi_reslimit_get_integer_limit(conn,
  54. li->li_reslimit_pagedlookthrough_handle, &limit) != SLAPI_RESLIMIT_STATUS_SUCCESS)
  55. {
  56. PR_Lock(li->li_config_mutex);
  57. if (li->li_pagedlookthroughlimit) {
  58. limit = li->li_pagedlookthroughlimit;
  59. } else {
  60. /* No paged search lookthroughlimit, so use dbi_db_t lookthroughlimit.
  61. * First check if we have a "resource limit" that applies to this
  62. * connection, otherwise use the global dbi_db_t lookthroughlimit
  63. */
  64. if (slapi_reslimit_get_integer_limit(conn,
  65. li->li_reslimit_lookthrough_handle, &limit) != SLAPI_RESLIMIT_STATUS_SUCCESS)
  66. {
  67. /* Default to global dbi_db_t lookthroughlimit */
  68. limit = li->li_lookthroughlimit;
  69. }
  70. }
  71. /* else set above */
  72. PR_Unlock(li->li_config_mutex);
  73. }
  74. } else {
  75. /* Regular search */
  76. if (slapi_reslimit_get_integer_limit(conn,
  77. li->li_reslimit_lookthrough_handle, &limit) != SLAPI_RESLIMIT_STATUS_SUCCESS)
  78. {
  79. /*
  80. * no limit associated with binder/connection or some other error
  81. * occurred. use the default.
  82. */
  83. PR_Lock(li->li_config_mutex);
  84. limit = li->li_lookthroughlimit;
  85. PR_Unlock(li->li_config_mutex);
  86. }
  87. }
  88. }
  89. return (limit);
  90. }
  91. int
  92. compute_allids_limit(Slapi_PBlock *pb, struct ldbminfo *li)
  93. {
  94. Slapi_Connection *conn = NULL;
  95. int limit;
  96. Slapi_Operation *op;
  97. slapi_pblock_get(pb, SLAPI_CONNECTION, &conn);
  98. slapi_pblock_get(pb, SLAPI_OPERATION, &op);
  99. if (slapi_reslimit_get_integer_limit(conn,
  100. li->li_reslimit_allids_handle, &limit) != SLAPI_RESLIMIT_STATUS_SUCCESS) {
  101. PR_Lock(li->li_config_mutex);
  102. limit = li->li_allidsthreshold;
  103. PR_Unlock(li->li_config_mutex);
  104. }
  105. if (op_is_pagedresults(op)) {
  106. if (slapi_reslimit_get_integer_limit(conn,
  107. li->li_reslimit_pagedallids_handle, &limit) != SLAPI_RESLIMIT_STATUS_SUCCESS) {
  108. PR_Lock(li->li_config_mutex);
  109. if (li->li_pagedallidsthreshold) {
  110. limit = li->li_pagedallidsthreshold;
  111. }
  112. PR_Unlock(li->li_config_mutex);
  113. }
  114. }
  115. return (limit);
  116. }
  117. /* don't free the berval, just clean it */
  118. static void
  119. berval_done(struct berval *val)
  120. {
  121. slapi_ch_free_string(&val->bv_val);
  122. }
  123. /*
  124. * We call this function as we exit ldbm_back_search
  125. */
  126. static int
  127. ldbm_back_search_cleanup(Slapi_PBlock *pb,
  128. struct ldbminfo *li __attribute__((unused)),
  129. sort_spec_thing *sort_control,
  130. int ldap_result,
  131. char *ldap_result_description,
  132. int function_result,
  133. struct vlv_request *vlv_request_control,
  134. struct backentry *e,
  135. IDList *candidates)
  136. {
  137. int estimate = 0; /* estimated search result count */
  138. backend *be;
  139. ldbm_instance *inst;
  140. back_search_result_set *sr = NULL;
  141. int free_candidates = 1;
  142. slapi_pblock_get(pb, SLAPI_BACKEND, &be);
  143. inst = (ldbm_instance *)be->be_instance_info;
  144. /*
  145. * In case SLAPI_BE_FLAG_DONT_BYPASS_FILTERTEST is set,
  146. * clean it up for the following sessions.
  147. */
  148. slapi_be_unset_flag(be, SLAPI_BE_FLAG_DONT_BYPASS_FILTERTEST);
  149. CACHE_RETURN(&inst->inst_cache, &e); /* NULL e is handled correctly */
  150. if (inst->inst_ref_count) {
  151. slapi_counter_decrement(inst->inst_ref_count);
  152. }
  153. if (sort_control != NULL) {
  154. sort_spec_free(sort_control);
  155. }
  156. if ((ldap_result != LDBM_SRCH_DEFAULT_RESULT) && (ldap_result != LDAP_SUCCESS)) {
  157. slapi_send_ldap_result(pb, ldap_result, NULL, ldap_result_description, 0, NULL);
  158. }
  159. /* code to free the result set if we don't need it */
  160. /* We get it and check to see if the structure was ever used */
  161. slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
  162. if (sr) {
  163. if (function_result) { /* failed case */
  164. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate);
  165. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, NULL);
  166. if (sr->sr_candidates == candidates) {
  167. free_candidates = 0;
  168. }
  169. delete_search_result_set(pb, &sr);
  170. } else if (sr->sr_candidates == candidates) { /* succeeded case */
  171. free_candidates = 0;
  172. }
  173. }
  174. if (free_candidates) {
  175. idl_free(&candidates);
  176. }
  177. if (vlv_request_control) {
  178. berval_done(&vlv_request_control->value);
  179. }
  180. return function_result;
  181. }
  182. static int
  183. ldbm_search_compile_filter(Slapi_Filter *f, void *arg __attribute__((unused)))
  184. {
  185. int rc = SLAPI_FILTER_SCAN_CONTINUE;
  186. if (f->f_choice == LDAP_FILTER_SUBSTRINGS) {
  187. char pat[BUFSIZ];
  188. char *p, *end, *bigpat = NULL;
  189. size_t size = 0;
  190. Slapi_Regex *re = NULL;
  191. const char *re_result = NULL;
  192. int i = 0;
  193. PR_ASSERT(NULL == f->f_un.f_un_sub.sf_private);
  194. /*
  195. * construct a regular expression corresponding to the filter
  196. */
  197. pat[0] = '\0';
  198. p = pat;
  199. end = pat + sizeof(pat) - 2; /* leave room for null */
  200. if (f->f_sub_initial != NULL) {
  201. size = strlen(f->f_sub_initial) + 1; /* add 1 for "^" */
  202. }
  203. while (f->f_sub_any && f->f_sub_any[i]) {
  204. size += strlen(f->f_sub_any[i++]) + 2; /* add 2 for ".*" */
  205. }
  206. if (f->f_sub_final != NULL) {
  207. size += strlen(f->f_sub_final) + 3; /* add 3 for ".*" and "$" */
  208. }
  209. size *= 2; /* doubled in case all filter chars need escaping (regex special chars) */
  210. size++; /* add 1 for null */
  211. if (p + size > end) {
  212. bigpat = slapi_ch_malloc(size);
  213. p = bigpat;
  214. }
  215. if (f->f_sub_initial != NULL) {
  216. *p++ = '^';
  217. p = filter_strcpy_special_ext(p, f->f_sub_initial, FILTER_STRCPY_ESCAPE_RECHARS);
  218. }
  219. for (i = 0; f->f_sub_any && f->f_sub_any[i]; i++) {
  220. /* ".*" + value */
  221. *p++ = '.';
  222. *p++ = '*';
  223. p = filter_strcpy_special_ext(p, f->f_sub_any[i], FILTER_STRCPY_ESCAPE_RECHARS);
  224. }
  225. if (f->f_sub_final != NULL) {
  226. /* ".*" + value */
  227. *p++ = '.';
  228. *p++ = '*';
  229. p = filter_strcpy_special_ext(p, f->f_sub_final, FILTER_STRCPY_ESCAPE_RECHARS);
  230. strcat(p, "$");
  231. }
  232. /* compile the regex */
  233. p = bigpat ? bigpat : pat;
  234. re = slapi_re_comp(p, &re_result);
  235. if (NULL == re) {
  236. slapi_log_err(SLAPI_LOG_ERR, "ldbm_search_compile_filter", "re_comp (%s) failed (%s): %s\n",
  237. pat, p, re_result ? re_result : "unknown");
  238. rc = SLAPI_FILTER_SCAN_ERROR;
  239. } else {
  240. char ebuf[BUFSIZ];
  241. slapi_log_err(SLAPI_LOG_TRACE, "ldbm_search_compile_filter", "re_comp (%s)\n",
  242. escape_string(p, ebuf));
  243. f->f_un.f_un_sub.sf_private = (void *)re;
  244. }
  245. } else if (f->f_choice == LDAP_FILTER_EQUALITY) {
  246. /* store the flags in the ava_private - should be ok - points
  247. to itself - no dangling references */
  248. f->f_un.f_un_ava.ava_private = &f->f_flags;
  249. }
  250. return rc;
  251. }
  252. static int
  253. ldbm_search_free_compiled_filter(Slapi_Filter *f, void *arg __attribute__((unused)))
  254. {
  255. int rc = SLAPI_FILTER_SCAN_CONTINUE;
  256. if ((f->f_choice == LDAP_FILTER_SUBSTRINGS) &&
  257. (f->f_un.f_un_sub.sf_private)) {
  258. slapi_re_free((Slapi_Regex *)f->f_un.f_un_sub.sf_private);
  259. f->f_un.f_un_sub.sf_private = NULL;
  260. } else if (f->f_choice == LDAP_FILTER_EQUALITY) {
  261. /* clear the flags in the ava_private */
  262. f->f_un.f_un_ava.ava_private = NULL;
  263. }
  264. return rc;
  265. }
  266. /*
  267. * Return values from ldbm_back_search are:
  268. *
  269. * 0: Success. A result set is in the pblock. No results have been
  270. * sent to the client.
  271. * 1: Success. The result has already been sent to the client.
  272. * -1: An error occurred, and results have been sent to the client.
  273. * -2: Disk Full. Abandon ship!
  274. */
  275. int
  276. ldbm_back_search(Slapi_PBlock *pb)
  277. {
  278. /* Search stuff */
  279. backend *be;
  280. ldbm_instance *inst;
  281. struct ldbminfo *li;
  282. struct backentry *e;
  283. IDList *candidates = NULL;
  284. const char *base;
  285. Slapi_DN *basesdn = NULL;
  286. int scope;
  287. LDAPControl **controls = NULL;
  288. Slapi_Operation *operation;
  289. entry_address *addr;
  290. int estimate = 0; /* estimated search result set size */
  291. /* SORT control stuff */
  292. int sort = 0;
  293. int vlv = 0;
  294. struct berval *sort_spec = NULL;
  295. int is_sorting_critical = 0;
  296. int is_sorting_critical_orig = 0;
  297. sort_spec_thing *sort_control = NULL;
  298. /* VLV control stuff */
  299. int virtual_list_view = 0;
  300. struct berval *vlv_spec = NULL;
  301. int is_vlv_critical = 0;
  302. struct vlv_request vlv_request_control;
  303. back_search_result_set *sr = NULL;
  304. /* Fix for bugid #394184, SD, 20 Jul 00 */
  305. int tmp_err = LDBM_SRCH_DEFAULT_RESULT;
  306. char *tmp_desc = NULL;
  307. /* end Fix for defect #394184 */
  308. int lookup_returned_allids = 0;
  309. int backend_count = 1;
  310. static int print_once = 1;
  311. back_txn txn = {NULL};
  312. int rc = 0;
  313. slapi_pblock_get(pb, SLAPI_BACKEND, &be);
  314. slapi_pblock_get(pb, SLAPI_OPERATION, &operation);
  315. slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &li);
  316. slapi_pblock_get(pb, SLAPI_SEARCH_TARGET_SDN, &basesdn);
  317. slapi_pblock_get(pb, SLAPI_TARGET_ADDRESS, &addr);
  318. slapi_pblock_get(pb, SLAPI_SEARCH_SCOPE, &scope);
  319. slapi_pblock_get(pb, SLAPI_REQCONTROLS, &controls);
  320. slapi_pblock_get(pb, SLAPI_BACKEND_COUNT, &backend_count);
  321. slapi_pblock_get(pb, SLAPI_TXN, &txn.back_txn_txn);
  322. if (!txn.back_txn_txn) {
  323. dblayer_txn_init(li, &txn);
  324. slapi_pblock_set(pb, SLAPI_TXN, txn.back_txn_txn);
  325. }
  326. if (NULL == basesdn) {
  327. slapi_send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL,
  328. "Null target DN", 0, NULL);
  329. return (-1);
  330. }
  331. inst = (ldbm_instance *)be->be_instance_info;
  332. if (inst && inst->inst_ref_count) {
  333. slapi_counter_increment(inst->inst_ref_count);
  334. } else {
  335. slapi_log_err(SLAPI_LOG_ERR,
  336. "ldbm_back_search", "Instance \"%s\" does not exist.\n",
  337. inst ? inst->inst_name : "null instance");
  338. return (-1);
  339. }
  340. base = slapi_sdn_get_dn(basesdn);
  341. /* Initialize the result set structure here because we need to use it during search processing */
  342. /* Beware that if we exit this routine sideways, we might leak this structure */
  343. sr = new_search_result_set(NULL, 0,
  344. compute_lookthrough_limit(pb, li));
  345. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET, sr);
  346. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate);
  347. /* clear this out so we can free it later */
  348. memset(&vlv_request_control, 0, sizeof(vlv_request_control));
  349. if (NULL != controls) {
  350. /* Are we being asked to sort the results ? */
  351. sort = slapi_control_present(controls, LDAP_CONTROL_SORTREQUEST, &sort_spec, &is_sorting_critical_orig);
  352. if (sort) {
  353. rc = parse_sort_spec(sort_spec, &sort_control);
  354. if (rc) {
  355. /* Badly formed SORT control */
  356. if (is_sorting_critical_orig) {
  357. /* RFC 4511 4.1.11 the server must not process the operation
  358. * and return LDAP_UNAVAILABLE_CRITICAL_EXTENSION
  359. */
  360. return ldbm_back_search_cleanup(pb, li, sort_control,
  361. LDAP_UNAVAILABLE_CRITICAL_EXTENSION, "Sort Control",
  362. SLAPI_FAIL_GENERAL, NULL, NULL, candidates);
  363. } else {
  364. PRUint64 conn_id;
  365. int op_id;
  366. /* Just ignore the control */
  367. sort = 0;
  368. slapi_pblock_get(pb, SLAPI_CONN_ID, &conn_id);
  369. slapi_pblock_get(pb, SLAPI_OPERATION_ID, &op_id);
  370. slapi_log_err(SLAPI_LOG_WARNING,
  371. "ldbm_back_search", "Sort control ignored for conn=%" PRIu64 " op=%d\n",
  372. conn_id, op_id);
  373. }
  374. } else {
  375. /* set this operation includes the server side sorting */
  376. operation->o_flags |= OP_FLAG_SERVER_SIDE_SORTING;
  377. }
  378. }
  379. is_sorting_critical = is_sorting_critical_orig;
  380. /* Are we to provide a virtual view of the list? */
  381. if ((vlv = slapi_control_present(controls, LDAP_CONTROL_VLVREQUEST, &vlv_spec, &is_vlv_critical))) {
  382. if (sort) {
  383. rc = vlv_parse_request_control(be, vlv_spec, &vlv_request_control);
  384. if (rc != LDAP_SUCCESS) {
  385. /* Badly formed VLV control */
  386. if (is_vlv_critical) {
  387. /* RFC 4511 4.1.11 the server must not process the operation
  388. * and return LDAP_UNAVAILABLE_CRITICAL_EXTENSION
  389. */
  390. return ldbm_back_search_cleanup(pb, li, sort_control,
  391. LDAP_UNAVAILABLE_CRITICAL_EXTENSION, "VLV Control", SLAPI_FAIL_GENERAL,
  392. &vlv_request_control, NULL, candidates);
  393. } else {
  394. PRUint64 conn_id;
  395. int op_id;
  396. /* Just ignore the control */
  397. virtual_list_view = 0;
  398. slapi_pblock_get(pb, SLAPI_CONN_ID, &conn_id);
  399. slapi_pblock_get(pb, SLAPI_OPERATION_ID, &op_id);
  400. slapi_log_err(SLAPI_LOG_WARNING,
  401. "ldbm_back_search", "VLV control ignored for conn=%" PRIu64 " op=%d\n",
  402. conn_id, op_id);
  403. }
  404. } else {
  405. {
  406. /* Access Control Check to see if the client is allowed to use the VLV Control. */
  407. Slapi_Entry *feature;
  408. char dn[128];
  409. char *dummyAttr = "dummy#attr";
  410. char *dummyAttrs[2] = {NULL, NULL};
  411. dummyAttrs[0] = dummyAttr;
  412. /* This dn is normalized. */
  413. PR_snprintf(dn, sizeof(dn), "dn: oid=%s,cn=features,cn=config", LDAP_CONTROL_VLVREQUEST);
  414. feature = slapi_str2entry(dn, 0);
  415. rc = plugin_call_acl_plugin(pb, feature, dummyAttrs, NULL, SLAPI_ACL_READ, ACLPLUGIN_ACCESS_DEFAULT, NULL);
  416. slapi_entry_free(feature);
  417. if (rc != LDAP_SUCCESS) {
  418. /* Client isn't allowed to do this. */
  419. return ldbm_back_search_cleanup(pb, li, sort_control,
  420. rc, "VLV Control", SLAPI_FAIL_GENERAL,
  421. &vlv_request_control, NULL, candidates);
  422. }
  423. }
  424. /*
  425. * Sorting must always be critical for VLV; Force it be so.
  426. */
  427. is_sorting_critical = 1;
  428. virtual_list_view = 1;
  429. }
  430. } else {
  431. /* Can't have a VLV control without a SORT control */
  432. return ldbm_back_search_cleanup(pb, li, sort_control,
  433. LDAP_SORT_CONTROL_MISSING, "VLV Control",
  434. SLAPI_FAIL_GENERAL, &vlv_request_control, NULL, candidates);
  435. }
  436. }
  437. }
  438. if ((virtual_list_view || sort) && backend_count > 0) {
  439. char *ctrlstr = NULL;
  440. struct vlv_response vlv_response = {0};
  441. if (virtual_list_view) {
  442. if (sort) {
  443. ctrlstr = "The VLV and sort controls cannot be processed";
  444. } else {
  445. ctrlstr = "The VLV control cannot be processed";
  446. }
  447. } else {
  448. if (sort) {
  449. ctrlstr = "The sort control cannot be processed";
  450. }
  451. }
  452. PR_ASSERT(NULL != ctrlstr);
  453. if (print_once) {
  454. slapi_log_err(SLAPI_LOG_WARNING,
  455. "ldbm_back_search", "%s "
  456. "When more than one backend is involved. "
  457. "VLV indexes that will never be used should be removed.\n",
  458. ctrlstr);
  459. print_once = 0;
  460. }
  461. /* 402380: mapping tree must refuse VLV and SORT control
  462. * when several backends are impacted by a search */
  463. if (0 != is_vlv_critical) {
  464. vlv_response.result = LDAP_UNWILLING_TO_PERFORM;
  465. vlv_make_response_control(pb, &vlv_response);
  466. if (sort) {
  467. sort_make_sort_response_control(pb, LDAP_UNWILLING_TO_PERFORM, NULL);
  468. }
  469. if (ISLEGACY(be)) {
  470. return ldbm_back_search_cleanup(pb, li, sort_control,
  471. LDAP_UNWILLING_TO_PERFORM, ctrlstr,
  472. SLAPI_FAIL_GENERAL, &vlv_request_control, NULL, candidates);
  473. } else {
  474. return ldbm_back_search_cleanup(pb, li, sort_control,
  475. LDAP_VIRTUAL_LIST_VIEW_ERROR, ctrlstr,
  476. SLAPI_FAIL_GENERAL, &vlv_request_control, NULL, candidates);
  477. }
  478. } else {
  479. if (0 != is_sorting_critical_orig) {
  480. if (virtual_list_view) {
  481. vlv_response.result = LDAP_UNWILLING_TO_PERFORM;
  482. vlv_make_response_control(pb, &vlv_response);
  483. }
  484. sort_make_sort_response_control(pb, LDAP_UNWILLING_TO_PERFORM, NULL);
  485. return ldbm_back_search_cleanup(pb, li, sort_control,
  486. LDAP_UNAVAILABLE_CRITICAL_EXTENSION, ctrlstr,
  487. SLAPI_FAIL_GENERAL, &vlv_request_control, NULL, candidates);
  488. } else /* vlv and sorting are not critical, so ignore the control */
  489. {
  490. if (virtual_list_view) {
  491. vlv_response.result = LDAP_UNWILLING_TO_PERFORM;
  492. vlv_make_response_control(pb, &vlv_response);
  493. }
  494. if (sort) {
  495. sort_make_sort_response_control(pb, LDAP_UNWILLING_TO_PERFORM, NULL);
  496. }
  497. sort = 0;
  498. virtual_list_view = 0;
  499. }
  500. }
  501. }
  502. /*
  503. * Get the base object for the search.
  504. * The entry "" will never be contained in the database,
  505. * so treat it as a special case.
  506. */
  507. if (*base == '\0') {
  508. e = NULL;
  509. } else {
  510. if ((e = find_entry(pb, be, addr, &txn, NULL)) == NULL) {
  511. /* error or referral sent by find_entry */
  512. return ldbm_back_search_cleanup(pb, li, sort_control,
  513. LDBM_SRCH_DEFAULT_RESULT, NULL, 1, &vlv_request_control, NULL, candidates);
  514. }
  515. }
  516. /* We have the base search entry and a callback to "cache_return" it.
  517. * Keep it into the operation to avoid additional cache fetch/return
  518. */
  519. if (e && be->be_entry_release) {
  520. operation_set_target_entry(operation, (void *) e);
  521. operation_set_target_entry_id(operation, e->ep_id);
  522. }
  523. /*
  524. * If this is a persistent search then the client is only
  525. * interested in entries that change, so we skip building
  526. * a candidate list.
  527. */
  528. if (operation_is_flag_set(operation, OP_FLAG_PS_CHANGESONLY)) {
  529. candidates = NULL;
  530. } else {
  531. struct timespec expire_time = {0};
  532. int lookthrough_limit = 0;
  533. struct vlv_response vlv_response_control;
  534. int abandoned = 0;
  535. int vlv_rc;
  536. /*
  537. * Build a list of IDs for this entry and scope
  538. */
  539. vlv_response_control.result = LDAP_SUCCESS;
  540. if ((NULL != controls) && (sort) && (vlv)) {
  541. /* This candidate list is for vlv, no need for sort only. */
  542. switch (vlv_search_build_candidate_list(pb, basesdn, &vlv_rc,
  543. sort_control,
  544. &vlv_request_control,
  545. &candidates, &vlv_response_control)) {
  546. case VLV_ACCESS_DENIED:
  547. return ldbm_back_search_cleanup(pb, li, sort_control,
  548. vlv_rc, "VLV Control",
  549. SLAPI_FAIL_GENERAL,
  550. &vlv_request_control, e, candidates);
  551. case VLV_BLD_LIST_FAILED:
  552. return ldbm_back_search_cleanup(pb, li, sort_control,
  553. vlv_response_control.result,
  554. NULL, SLAPI_FAIL_GENERAL,
  555. &vlv_request_control, e, candidates);
  556. case LDAP_SUCCESS:
  557. /* Log to the access log the particulars of this sort request */
  558. /* Log message looks like this: SORT <key list useful for input
  559. * to ldapsearch> <#candidates> | <unsortable> */
  560. sort_log_access(pb, sort_control, NULL);
  561. /* Since a pre-computed index was found for the VLV Search then
  562. * the candidate list now contains exactly what should be
  563. * returned.
  564. * There's no need to sort or trim the candidate list.
  565. *
  566. * However, the client will be expecting a Sort Response control
  567. */
  568. if (LDAP_SUCCESS !=
  569. sort_make_sort_response_control(pb, 0, NULL)) {
  570. return ldbm_back_search_cleanup(pb, li, sort_control,
  571. LDAP_OPERATIONS_ERROR,
  572. "Sort Response Control",
  573. SLAPI_FAIL_GENERAL,
  574. &vlv_request_control, e, candidates);
  575. }
  576. }
  577. }
  578. if (candidates == NULL) {
  579. int rc = build_candidate_list(pb, be, e, base, scope,
  580. &lookup_returned_allids, &candidates);
  581. if (rc) {
  582. /* Error result sent by build_candidate_list */
  583. return ldbm_back_search_cleanup(pb, li, sort_control,
  584. LDBM_SRCH_DEFAULT_RESULT, NULL, rc,
  585. &vlv_request_control, e, candidates);
  586. }
  587. /*
  588. * If we're sorting then we must check what administrative
  589. * limits should be imposed. Work out at what time to give
  590. * up, and how many entries we should sift through.
  591. */
  592. if (sort && (NULL != candidates)) {
  593. int tlimit = 0;
  594. slapi_pblock_get(pb, SLAPI_SEARCH_TIMELIMIT, &tlimit);
  595. slapi_operation_time_expiry(operation, (time_t)tlimit, &expire_time);
  596. lookthrough_limit = compute_lookthrough_limit(pb, li);
  597. }
  598. /*
  599. * If we're presenting a virtual list view, then apply the
  600. * search filter before sorting.
  601. */
  602. if (virtual_list_view && candidates) {
  603. IDList *idl = NULL;
  604. Slapi_Filter *filter = NULL;
  605. slapi_pblock_get(pb, SLAPI_SEARCH_FILTER, &filter);
  606. rc = LDAP_OPERATIONS_ERROR;
  607. if (filter) {
  608. rc = vlv_filter_candidates(be, pb, candidates, basesdn,
  609. scope, filter, &idl,
  610. lookthrough_limit, &expire_time);
  611. }
  612. switch (rc) {
  613. case LDAP_SUCCESS: /* Everything OK */
  614. case LDAP_TIMELIMIT_EXCEEDED: /* Timeout */
  615. case LDAP_ADMINLIMIT_EXCEEDED: /* Admin limit exceeded */
  616. vlv_response_control.result = rc;
  617. idl_free(&candidates);
  618. candidates = idl;
  619. break;
  620. case LDAP_UNWILLING_TO_PERFORM: /* Too hard */
  621. default:
  622. return ldbm_back_search_cleanup(pb, li, sort_control,
  623. rc, NULL, -1,
  624. &vlv_request_control, e, candidates);
  625. }
  626. if (is_vlv_critical && rc) {
  627. idl_free(&candidates);
  628. candidates = idl_alloc(0);
  629. tmp_err = rc;
  630. tmp_desc = "VLV Response Control";
  631. goto vlv_bail;
  632. }
  633. }
  634. /*
  635. * Client wants the server to sort the results.
  636. */
  637. if (sort) {
  638. if (NULL == candidates) {
  639. /* Even if candidates is NULL, we have to return a sort
  640. * response control with the LDAP_SUCCESS return code. */
  641. if (LDAP_SUCCESS !=
  642. sort_make_sort_response_control(pb, LDAP_SUCCESS, NULL)) {
  643. return ldbm_back_search_cleanup(pb, li, sort_control,
  644. LDAP_PROTOCOL_ERROR,
  645. "Sort Response Control", -1,
  646. &vlv_request_control, e, candidates);
  647. }
  648. } else {
  649. /* Before we haste off to sort the candidates, we need to
  650. * prepare some information for the purpose of imposing the
  651. * administrative limits.
  652. * We figure out the time when the time limit will be up.
  653. * We can't use the size limit because we might be sorting
  654. * a candidate list larger than the result set.
  655. * But, we can use the lookthrough limit---we count each
  656. * time we access an entry as one look and act accordingly.
  657. */
  658. char *sort_error_type = NULL;
  659. int sort_return_value = 0;
  660. /* Don't log internal operations */
  661. if (!operation_is_flag_set(operation, OP_FLAG_INTERNAL)) {
  662. /* Log to the access log the particulars of this
  663. * sort request */
  664. /* Log message looks like this: SORT <key list useful for
  665. * input to ldapsearch> <#candidates> | <unsortable> */
  666. sort_log_access(pb, sort_control, candidates);
  667. }
  668. sort_return_value = sort_candidates(be, lookthrough_limit,
  669. &expire_time, pb, candidates,
  670. sort_control,
  671. &sort_error_type);
  672. /* Fix for bugid # 394184, SD, 20 Jul 00 */
  673. /* replace the hard coded return value by the appropriate
  674. * LDAP error code */
  675. switch (sort_return_value) {
  676. case LDAP_SUCCESS:
  677. /*
  678. * we don't want to override an error from vlv
  679. * vlv_response_control.result= LDAP_SUCCESS;
  680. */
  681. break;
  682. case LDAP_PROTOCOL_ERROR: /* A protocol error */
  683. return ldbm_back_search_cleanup(pb, li, sort_control,
  684. LDAP_PROTOCOL_ERROR,
  685. "Sort Control", -1,
  686. &vlv_request_control, e, candidates);
  687. case LDAP_UNWILLING_TO_PERFORM: /* Too hard */
  688. case LDAP_OPERATIONS_ERROR: /* Operation error */
  689. case LDAP_TIMELIMIT_EXCEEDED: /* Timeout */
  690. case LDAP_ADMINLIMIT_EXCEEDED: /* Admin limit exceeded */
  691. if (!vlv_response_control.result) {
  692. vlv_response_control.result = sort_return_value;
  693. }
  694. break;
  695. case LDAP_OTHER: /* Abandoned */
  696. abandoned = 1; /* So that we don't return a result code */
  697. is_sorting_critical = 1; /* In order to have the results
  698. discarded */
  699. break;
  700. default: /* Should never get here */
  701. break;
  702. }
  703. /* End fix for bug # 394184 */
  704. /*
  705. * If the sort control was marked as critical, and there was
  706. * an error in sorting, don't return any entries, and return
  707. * unavailableCriticalExtension in the searchResultDone message.
  708. */
  709. /* Fix for bugid #394184, SD, 05 Jul 00 */
  710. /* we were not actually returning unavailableCriticalExtension;
  711. now fixed (hopefully !) */
  712. if (is_sorting_critical && sort_return_value) {
  713. idl_free(&candidates);
  714. candidates = idl_alloc(0);
  715. tmp_err = sort_return_value;
  716. tmp_desc = "Sort Response Control";
  717. }
  718. /* end Fix for bugid #394184 */
  719. /* Generate the control returned to the client to indicate
  720. * sort result */
  721. if (LDAP_SUCCESS != sort_make_sort_response_control(pb,
  722. sort_return_value, sort_error_type)) {
  723. return ldbm_back_search_cleanup(pb, li, sort_control,
  724. (abandoned ? LDBM_SRCH_DEFAULT_RESULT : LDAP_PROTOCOL_ERROR),
  725. "Sort Response Control", -1,
  726. &vlv_request_control, e, candidates);
  727. }
  728. }
  729. }
  730. /*
  731. * If we're presenting a virtual list view, then the candidate list
  732. * must be trimmed down to just the range of entries requested.
  733. */
  734. if (virtual_list_view) {
  735. if (candidates && (candidates->b_nids > 0) &&
  736. !vlv_response_control.result) {
  737. IDList *idl = NULL;
  738. back_txn txn = {NULL};
  739. slapi_pblock_get(pb, SLAPI_TXN, &txn.back_txn_txn);
  740. vlv_response_control.result =
  741. vlv_trim_candidates_txn(be, candidates, sort_control,
  742. &vlv_request_control, &idl, &vlv_response_control, &txn);
  743. if (vlv_response_control.result == 0) {
  744. idl_free(&candidates);
  745. candidates = idl;
  746. } else {
  747. return ldbm_back_search_cleanup(pb, li, sort_control,
  748. vlv_response_control.result,
  749. NULL, -1,
  750. &vlv_request_control, e, candidates);
  751. }
  752. } else {
  753. vlv_response_control.targetPosition = 0;
  754. vlv_response_control.contentCount = 0;
  755. /* vlv_response_control.result = LDAP_SUCCESS; Don't override */
  756. }
  757. }
  758. }
  759. vlv_bail:
  760. if (virtual_list_view) {
  761. if (LDAP_SUCCESS !=
  762. vlv_make_response_control(pb, &vlv_response_control)) {
  763. return ldbm_back_search_cleanup(pb, li, sort_control,
  764. (abandoned ? LDBM_SRCH_DEFAULT_RESULT : LDAP_PROTOCOL_ERROR),
  765. "VLV Response Control", -1,
  766. &vlv_request_control, e, candidates);
  767. }
  768. /* Log the VLV operation */
  769. vlv_print_access_log(pb, &vlv_request_control, &vlv_response_control);
  770. }
  771. }
  772. /*
  773. * if the candidate list is an allids list, arrange for access log
  774. * to record that fact.
  775. */
  776. if (NULL != candidates && ALLIDS(candidates)) {
  777. unsigned int opnote;
  778. int ri = 0;
  779. int rii = 0;
  780. int pr_idx = -1;
  781. Connection *pb_conn = NULL;
  782. Operation *pb_op = NULL;
  783. struct slapdplugin *plugin = NULL;
  784. struct slapi_componentid *cid = NULL;
  785. char *filter_str;
  786. char *plugin_dn;
  787. char *base_dn;
  788. int32_t internal_op = operation_is_flag_set(operation, OP_FLAG_INTERNAL);
  789. uint64_t connid;
  790. int32_t op_id;
  791. int32_t op_internal_id;
  792. int32_t op_nested_count;
  793. /*
  794. * Return error if require index is set
  795. */
  796. PR_Lock(inst->inst_config_mutex);
  797. ri = inst->require_index;
  798. rii = inst->require_internalop_index;
  799. PR_Unlock(inst->inst_config_mutex);
  800. if ((internal_op && rii) || (!internal_op && ri)) {
  801. idl_free(&candidates);
  802. candidates = idl_alloc(0);
  803. tmp_err = LDAP_UNWILLING_TO_PERFORM;
  804. tmp_desc = "Search is not indexed";
  805. }
  806. /*
  807. * When an search is fully unindexed we need to log the
  808. * details as these kinds of searches can cause issues with bdb db
  809. * locks being exhausted. This will help expose what indexing is
  810. * missing.
  811. */
  812. slapi_pblock_get(pb, SLAPI_OPERATION, &pb_op);
  813. slapi_pblock_get(pb, SLAPI_SEARCH_STRFILTER, &filter_str);
  814. slapi_pblock_get(pb, SLAPI_TARGET_DN, &base_dn);
  815. if (internal_op) {
  816. /* Get the plugin that triggered this internal search */
  817. slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &cid);
  818. if (cid) {
  819. plugin = (struct slapdplugin *)cid->sci_plugin;
  820. } else {
  821. slapi_pblock_get(pb, SLAPI_PLUGIN, &plugin);
  822. }
  823. plugin_dn = plugin_get_dn(plugin);
  824. get_internal_conn_op(&connid, &op_id, &op_internal_id, &op_nested_count);
  825. slapi_log_err(SLAPI_LOG_NOTICE, "ldbm_back_search",
  826. "Internal unindexed search: source (%s) search base=\"%s\" scope=%d filter=\"%s\" conn=%" PRIu64 " op=%d (internal op=%d count=%d)\n",
  827. plugin_dn, base_dn, scope, filter_str, connid, op_id, op_internal_id, op_nested_count);
  828. slapi_ch_free_string(&plugin_dn);
  829. } else {
  830. slapi_log_err(SLAPI_LOG_NOTICE, "ldbm_back_search",
  831. "Unindexed search: search base=\"%s\" scope=%d filter=\"%s\" conn=%" PRIu64 " op=%d\n",
  832. base_dn, scope, filter_str, pb_op->o_connid, pb_op->o_opid);
  833. }
  834. opnote = slapi_pblock_get_operation_notes(pb);
  835. opnote |= SLAPI_OP_NOTE_FULL_UNINDEXED; /* the full filter leads to an unindexed search */
  836. opnote &= ~SLAPI_OP_NOTE_UNINDEXED; /* this note is useless because FULL_UNINDEXED includes UNINDEXED */
  837. slapi_pblock_set_operation_notes(pb, opnote);
  838. slapi_pblock_get(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx);
  839. slapi_pblock_get(pb, SLAPI_CONNECTION, &pb_conn);
  840. pagedresults_set_unindexed(pb_conn, pb_op, pr_idx);
  841. }
  842. sr->sr_candidates = candidates;
  843. sr->sr_virtuallistview = virtual_list_view;
  844. /* Set the estimated search result count for simple paged results */
  845. if (sr->sr_candidates && !ALLIDS(sr->sr_candidates)) {
  846. estimate = IDL_NIDS(sr->sr_candidates);
  847. }
  848. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate);
  849. /* check to see if we can skip the filter test */
  850. if (li->li_filter_bypass && NULL != candidates && !virtual_list_view && !lookup_returned_allids) {
  851. Slapi_Filter *filter = NULL;
  852. slapi_pblock_get(pb, SLAPI_SEARCH_FILTER, &filter);
  853. if (NULL == filter) {
  854. tmp_err = LDAP_OPERATIONS_ERROR;
  855. tmp_desc = "Filter is not set";
  856. goto bail;
  857. }
  858. if (can_skip_filter_test(pb, filter, scope, candidates)) {
  859. sr->sr_flags |= SR_FLAG_CAN_SKIP_FILTER_TEST;
  860. }
  861. }
  862. /* if we need to perform the filter test, pre-digest the filter to
  863. speed up the filter test */
  864. if (!(sr->sr_flags & SR_FLAG_CAN_SKIP_FILTER_TEST) ||
  865. li->li_filter_bypass_check) {
  866. int rc = 0, filt_errs = 0;
  867. Slapi_Filter *filter = NULL;
  868. slapi_pblock_get(pb, SLAPI_SEARCH_FILTER, &filter);
  869. if (NULL == filter) {
  870. tmp_err = LDAP_OPERATIONS_ERROR;
  871. tmp_desc = "Filter is not set";
  872. goto bail;
  873. }
  874. slapi_filter_free(sr->sr_norm_filter, 1);
  875. sr->sr_norm_filter = slapi_filter_dup(filter);
  876. /* step 1 - normalize all of the values used in the search filter */
  877. slapi_filter_normalize(sr->sr_norm_filter, PR_TRUE /* normalize values too */);
  878. /* step 2 - pre-compile the substr regex and the equality flags */
  879. rc = slapi_filter_apply(sr->sr_norm_filter, ldbm_search_compile_filter,
  880. NULL, &filt_errs);
  881. if (rc != SLAPI_FILTER_SCAN_NOMORE) {
  882. slapi_log_err(SLAPI_LOG_ERR,
  883. "ldbm_back_search", "Could not pre-compile the search filter - error %d %d\n",
  884. rc, filt_errs);
  885. if (rc == SLAPI_FILTER_SCAN_ERROR) {
  886. tmp_err = LDAP_OPERATIONS_ERROR;
  887. tmp_desc = "Could not compile regex for filter matching";
  888. }
  889. }
  890. }
  891. bail:
  892. /* Fix for bugid #394184, SD, 05 Jul 00 */
  893. /* tmp_err == LDBM_SRCH_DEFAULT_RESULT: no error */
  894. return ldbm_back_search_cleanup(pb, li, sort_control, tmp_err, tmp_desc,
  895. (tmp_err == LDBM_SRCH_DEFAULT_RESULT ? 0 : LDBM_SRCH_DEFAULT_RESULT),
  896. &vlv_request_control, NULL, candidates);
  897. /* end Fix for bugid #394184 */
  898. }
  899. /*
  900. * Build a candidate list for this backentry and scope.
  901. * Could be a BASE, ONELEVEL, or SUBTREE search.
  902. *
  903. * Returns:
  904. * 0 - success
  905. * <0 - fail
  906. *
  907. */
  908. static int
  909. build_candidate_list(Slapi_PBlock *pb, backend *be, struct backentry *e, const char *base, int scope, int *lookup_returned_allidsp, IDList **candidates)
  910. {
  911. struct ldbminfo *li = (struct ldbminfo *)be->be_database->plg_private;
  912. int managedsait = 0;
  913. Slapi_Filter *filter = NULL;
  914. int err = 0;
  915. int r = 0;
  916. slapi_pblock_get(pb, SLAPI_SEARCH_FILTER, &filter);
  917. if (NULL == filter) {
  918. slapi_send_ldap_result(pb, LDAP_PROTOCOL_ERROR, NULL, "No filter", 0, NULL);
  919. r = SLAPI_FAIL_GENERAL;
  920. goto bail;
  921. }
  922. slapi_pblock_get(pb, SLAPI_MANAGEDSAIT, &managedsait);
  923. switch (scope) {
  924. case LDAP_SCOPE_BASE:
  925. *candidates = base_candidates(pb, e);
  926. break;
  927. case LDAP_SCOPE_ONELEVEL:
  928. *candidates = onelevel_candidates(pb, be, base, e, filter, managedsait,
  929. lookup_returned_allidsp, &err);
  930. break;
  931. case LDAP_SCOPE_SUBTREE:
  932. *candidates = subtree_candidates(pb, be, base, e, filter, managedsait,
  933. lookup_returned_allidsp, &err);
  934. break;
  935. default:
  936. slapi_send_ldap_result(pb, LDAP_PROTOCOL_ERROR, NULL, "Bad scope", 0, NULL);
  937. r = SLAPI_FAIL_GENERAL;
  938. }
  939. if (0 != err && DBI_RC_NOTFOUND != err) {
  940. slapi_log_err(SLAPI_LOG_ERR, "build_candidate_list", "Database error %d\n", err);
  941. slapi_send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL, NULL,
  942. 0, NULL);
  943. if (LDBM_OS_ERR_IS_DISKFULL(err))
  944. r = return_on_disk_full(li);
  945. else
  946. r = SLAPI_FAIL_GENERAL;
  947. }
  948. bail:
  949. /*
  950. * If requested, set a flag to indicate whether the indexed
  951. * lookup returned an ALLIDs block. Note that this is taken care of
  952. * above already for subtree searches.
  953. */
  954. if (NULL != lookup_returned_allidsp) {
  955. if (0 == err || DBI_RC_NOTFOUND == err) {
  956. if (!(*lookup_returned_allidsp) && LDAP_SCOPE_SUBTREE != scope) {
  957. *lookup_returned_allidsp =
  958. (NULL != *candidates && ALLIDS(*candidates));
  959. }
  960. } else {
  961. *lookup_returned_allidsp = 0;
  962. }
  963. }
  964. slapi_log_err(SLAPI_LOG_TRACE, "build_candidate_list", "Candidate list has %lu ids\n",
  965. *candidates ? (*candidates)->b_nids : 0L);
  966. return r;
  967. }
  968. /*
  969. * Build a candidate list for a BASE scope search.
  970. */
  971. static IDList *
  972. base_candidates(Slapi_PBlock *pb __attribute__((unused)), struct backentry *e)
  973. {
  974. IDList *idl = idl_alloc(1);
  975. idl_append(idl, NULL == e ? 0 : e->ep_id);
  976. return (idl);
  977. }
  978. /*
  979. * Modify the filter to include entries of the referral objectclass
  980. *
  981. * make (|(originalfilter)(objectclass=referral))
  982. *
  983. * "focref, forr" are temporary filters which the caller must free
  984. * non-recursively when done with the returned filter.
  985. */
  986. static Slapi_Filter *
  987. create_referral_filter(Slapi_Filter *filter, Slapi_Filter **focref, Slapi_Filter **forr)
  988. {
  989. char *buf = slapi_ch_strdup("objectclass=referral");
  990. *focref = slapi_str2filter(buf);
  991. *forr = slapi_filter_join(LDAP_FILTER_OR, filter, *focref);
  992. slapi_ch_free((void **)&buf);
  993. return *forr;
  994. }
  995. /*
  996. * Modify the filter to be a one level search.
  997. *
  998. * (&(parentid=idofbase)(|(originalfilter)(objectclass=referral)))
  999. *
  1000. * "fid2kids, focref, fand, forr" are temporary filters which the
  1001. * caller must free'd non-recursively when done with the returned filter.
  1002. *
  1003. * This function is exported for the VLV code to use.
  1004. */
  1005. Slapi_Filter *
  1006. create_onelevel_filter(Slapi_Filter *filter, const struct backentry *baseEntry, int managedsait, Slapi_Filter **fid2kids, Slapi_Filter **focref, Slapi_Filter **fand, Slapi_Filter **forr)
  1007. {
  1008. Slapi_Filter *ftop = filter;
  1009. char buf[40];
  1010. if (!managedsait) {
  1011. ftop = create_referral_filter(filter, focref, forr);
  1012. }
  1013. sprintf(buf, "parentid=%lu", (u_long)(baseEntry != NULL ? baseEntry->ep_id : 0));
  1014. *fid2kids = slapi_str2filter(buf);
  1015. *fand = slapi_filter_join(LDAP_FILTER_AND, ftop, *fid2kids);
  1016. return *fand;
  1017. }
  1018. /*
  1019. * Build a candidate list for a ONELEVEL scope search.
  1020. */
  1021. static IDList *
  1022. onelevel_candidates(
  1023. Slapi_PBlock *pb,
  1024. backend *be,
  1025. const char *base,
  1026. struct backentry *e,
  1027. Slapi_Filter *filter,
  1028. int managedsait,
  1029. int *lookup_returned_allidsp,
  1030. int *err)
  1031. {
  1032. Slapi_Filter *fid2kids = NULL;
  1033. Slapi_Filter *focref = NULL;
  1034. Slapi_Filter *fand = NULL;
  1035. Slapi_Filter *forr = NULL;
  1036. Slapi_Filter *ftop = NULL;
  1037. IDList *candidates;
  1038. /*
  1039. * modify the filter to be something like this:
  1040. *
  1041. * (&(parentid=idofbase)(|(originalfilter)(objectclass=referral)))
  1042. */
  1043. ftop = create_onelevel_filter(filter, e, managedsait, &fid2kids, &focref, &fand, &forr);
  1044. /* from here, it's just like subtree_candidates */
  1045. candidates = filter_candidates(pb, be, base, ftop, NULL, 0, err);
  1046. *lookup_returned_allidsp = slapi_be_is_flag_set(be, SLAPI_BE_FLAG_DONT_BYPASS_FILTERTEST);
  1047. /* free up just the filter stuff we allocated above */
  1048. slapi_filter_free(fid2kids, 0);
  1049. slapi_filter_free(fand, 0);
  1050. slapi_filter_free(forr, 0);
  1051. slapi_filter_free(focref, 0);
  1052. return (candidates);
  1053. }
  1054. /*
  1055. * We need to modify the filter to be something like this:
  1056. *
  1057. * (|(originalfilter)(objectclass=referral))
  1058. *
  1059. * the "objectclass=referral" part is used to select referrals to return.
  1060. * it is only included if the managedsait service control is not set.
  1061. *
  1062. * This function is exported for the VLV code to use.
  1063. */
  1064. Slapi_Filter *
  1065. create_subtree_filter(Slapi_Filter *filter, int managedsait, Slapi_Filter **focref, Slapi_Filter **forr)
  1066. {
  1067. Slapi_Filter *ftop = filter;
  1068. if (!managedsait) {
  1069. ftop = create_referral_filter(filter, focref, forr);
  1070. }
  1071. return ftop;
  1072. }
  1073. /*
  1074. * Build a candidate list for a SUBTREE scope search.
  1075. */
  1076. IDList *
  1077. subtree_candidates(
  1078. Slapi_PBlock *pb,
  1079. backend *be,
  1080. const char *base,
  1081. const struct backentry *e,
  1082. Slapi_Filter *filter,
  1083. int managedsait,
  1084. int *allids_before_scopingp,
  1085. int *err)
  1086. {
  1087. Slapi_Filter *focref = NULL;
  1088. Slapi_Filter *forr = NULL;
  1089. Slapi_Filter *ftop = NULL;
  1090. IDList *candidates;
  1091. PRBool has_tombstone_filter;
  1092. int isroot = 0;
  1093. struct ldbminfo *li = (struct ldbminfo *)be->be_database->plg_private;
  1094. int allidslimit = compute_allids_limit(pb, li);
  1095. Operation *op = NULL;
  1096. PRBool is_bulk_import = PR_FALSE;
  1097. /* make (|(originalfilter)(objectclass=referral)) */
  1098. ftop = create_subtree_filter(filter, managedsait, &focref, &forr);
  1099. /* Fetch a candidate list for the original filter */
  1100. candidates = filter_candidates_ext(pb, be, base, ftop, NULL, 0, err, allidslimit);
  1101. slapi_filter_free(forr, 0);
  1102. slapi_filter_free(focref, 0);
  1103. /* set 'allids before scoping' flag */
  1104. if (NULL != allids_before_scopingp) {
  1105. *allids_before_scopingp = (NULL != candidates && ALLIDS(candidates));
  1106. }
  1107. has_tombstone_filter = (filter->f_flags & SLAPI_FILTER_TOMBSTONE);
  1108. slapi_pblock_get(pb, SLAPI_REQUESTOR_ISROOT, &isroot);
  1109. /* Check if it is for bulk import. */
  1110. slapi_pblock_get(pb, SLAPI_OPERATION, &op);
  1111. if (op && entryrdn_get_switch() && operation_is_flag_set(op, OP_FLAG_INTERNAL) &&
  1112. operation_is_flag_set(op, OP_FLAG_BULK_IMPORT)) {
  1113. is_bulk_import = PR_TRUE;
  1114. }
  1115. /*
  1116. * Apply the DN components if the candidate list is greater than
  1117. * our threshold, and if the filter is not "(objectclass=nstombstone)",
  1118. * since tombstone entries are not indexed in the ancestorid index.
  1119. * Note: they are indexed in the entryrdn index.
  1120. */
  1121. if (candidates != NULL && (idl_length(candidates) > FILTER_TEST_THRESHOLD) && e) {
  1122. IDList *tmp = candidates, *descendants = NULL;
  1123. back_txn txn = {NULL};
  1124. slapi_pblock_get(pb, SLAPI_TXN, &txn.back_txn_txn);
  1125. if (entryrdn_get_noancestorid()) {
  1126. /* subtree-rename: on && no ancestorid */
  1127. *err = entryrdn_get_subordinates(be,
  1128. slapi_entry_get_sdn_const(e->ep_entry),
  1129. e->ep_id, &descendants, &txn, 0);
  1130. idl_insert(&descendants, e->ep_id);
  1131. candidates = idl_intersection(be, candidates, descendants);
  1132. idl_free(&tmp);
  1133. idl_free(&descendants);
  1134. } else if (!has_tombstone_filter && !is_bulk_import) {
  1135. *err = ldbm_ancestorid_read_ext(be, &txn, e->ep_id, &descendants, allidslimit);
  1136. idl_insert(&descendants, e->ep_id);
  1137. candidates = idl_intersection(be, candidates, descendants);
  1138. idl_free(&tmp);
  1139. idl_free(&descendants);
  1140. } /* else == has_tombstone_filter OR is_bulk_import: do nothing */
  1141. }
  1142. return (candidates);
  1143. }
  1144. static int grok_filter(struct slapi_filter *f);
  1145. /* Helper function for can_skip_filter_test() */
  1146. static int
  1147. grok_filter_not_subtype(struct slapi_filter *f)
  1148. {
  1149. /* If we haven't determined that we can't skip the filter test already,
  1150. * do one last check for attribute subtypes. We don't need to worry
  1151. * about any complex filters here since grok_filter() will have already
  1152. * assumed that we can't skip the filter test in those cases. */
  1153. int rc = 1;
  1154. char *type = NULL;
  1155. char *basetype = NULL;
  1156. /* We don't need to free type since that's taken
  1157. * care of when the filter is free'd later. We
  1158. * do need to free basetype when we are done. */
  1159. slapi_filter_get_attribute_type(f, &type);
  1160. basetype = slapi_attr_basetype(type, NULL, 0);
  1161. /* Is the filter using an attribute subtype? */
  1162. if (strcasecmp(type, basetype) != 0) {
  1163. /* If so, we can't optimize since attribute subtypes
  1164. * are simply indexed under their basetype attribute.
  1165. * The basetype index has no knowledge of the subtype
  1166. * itself. In the future, we should add support for
  1167. * indexing the subtypes so we can optimize this type
  1168. * of search. */
  1169. rc = 0;
  1170. }
  1171. slapi_ch_free_string(&basetype);
  1172. return rc;
  1173. }
  1174. static int
  1175. grok_filter(struct slapi_filter *f)
  1176. {
  1177. switch (f->f_choice) {
  1178. case LDAP_FILTER_EQUALITY:
  1179. /* If there's an ID list and an equality filter, we can skip the filter test */
  1180. return grok_filter_not_subtype(f);
  1181. case LDAP_FILTER_SUBSTRINGS:
  1182. return 0;
  1183. case LDAP_FILTER_GE:
  1184. return grok_filter_not_subtype(f);
  1185. case LDAP_FILTER_LE:
  1186. return grok_filter_not_subtype(f);
  1187. case LDAP_FILTER_PRESENT:
  1188. /* If there's an ID list, and a presence filter, we can skip the filter test */
  1189. return grok_filter_not_subtype(f);
  1190. case LDAP_FILTER_APPROX:
  1191. return 0;
  1192. case LDAP_FILTER_EXTENDED:
  1193. return 0;
  1194. case LDAP_FILTER_AND:
  1195. /* Unless we check to see whether the presence and equality branches
  1196. * of the search filter were all indexed, we get things wrong here,
  1197. * so let's punt for now
  1198. */
  1199. if (f->f_and->f_next == NULL) {
  1200. /* there is only one AND component,
  1201. * if it is a simple filter, we can skip it
  1202. */
  1203. return grok_filter(f->f_and);
  1204. } else {
  1205. return 0;
  1206. }
  1207. case LDAP_FILTER_OR:
  1208. return 0;
  1209. case LDAP_FILTER_NOT:
  1210. return 0;
  1211. default:
  1212. return 0;
  1213. }
  1214. }
  1215. /* Routine which says whether or not the indices produced a "correct" answer */
  1216. static int
  1217. can_skip_filter_test(
  1218. Slapi_PBlock *pb __attribute__((unused)),
  1219. struct slapi_filter *f,
  1220. int scope,
  1221. IDList *idl)
  1222. {
  1223. int rc = 0;
  1224. /* Is the ID list ALLIDS ? */
  1225. if (ALLIDS(idl)) {
  1226. /* If so, then can't optimize */
  1227. return rc;
  1228. }
  1229. /* Is this a base scope search? */
  1230. if (scope == LDAP_SCOPE_BASE) {
  1231. /*
  1232. * If so, then we can't optimize. Why not? Because we only consult
  1233. * the entrydn/entryrdn index in producing our 1 candidate, and that
  1234. * means we have not used the filter to produce the candidate list.
  1235. */
  1236. return rc;
  1237. }
  1238. /* Grok the filter and tell me if it has only equality components in it */
  1239. rc = grok_filter(f);
  1240. return rc;
  1241. }
  1242. /* The reference on the target_entry (base search) is stored in the operation
  1243. * This is to prevent additional cache find/return that require cache lock.
  1244. *
  1245. * The target entry is acquired during be->be_search (when building the candidate list).
  1246. * and is returned once the operation completes (or fail).
  1247. *
  1248. * The others entries sent back to the client have been acquired/returned during send_results_ext.
  1249. * If the target entry is sent back to the client it is not returned (refcnt--) during the send_results_ext.
  1250. *
  1251. * This function returns(refcnt-- in the entry cache) the entry unless it is
  1252. * the target_entry (base search). target_entry will be return once the operation
  1253. * completes
  1254. */
  1255. static void
  1256. non_target_cache_return(Slapi_Operation *op, struct cache *cache, struct backentry **e)
  1257. {
  1258. if (e && (*e != operation_get_target_entry(op))) {
  1259. CACHE_RETURN(cache, e);
  1260. }
  1261. }
  1262. /*
  1263. * Return the next entry in the result set. The entry is returned
  1264. * in the pblock.
  1265. * Returns 0 normally. If -1 is returned, it means that some
  1266. * exceptional condition, e.g. timelimit exceeded has occurred,
  1267. * and this routine has sent a result to the client. If zero
  1268. * is returned and no entry is available in the PBlock, then
  1269. * we've iterated through all the entries.
  1270. */
  1271. int
  1272. ldbm_back_next_search_entry(Slapi_PBlock *pb)
  1273. {
  1274. backend *be;
  1275. ldbm_instance *inst;
  1276. struct ldbminfo *li;
  1277. int scope;
  1278. int managedsait;
  1279. Slapi_Attr *attr;
  1280. Slapi_Filter *filter;
  1281. back_search_result_set *sr;
  1282. ID id;
  1283. struct backentry *e;
  1284. int nentries;
  1285. struct timespec expire_time;
  1286. int tlimit, llimit, slimit, isroot;
  1287. struct berval **urls = NULL;
  1288. int err;
  1289. Slapi_DN *basesdn = NULL;
  1290. char *target_uniqueid;
  1291. int rc = 0;
  1292. int estimate = 0; /* estimated search result count */
  1293. back_txn txn = {NULL};
  1294. int pr_idx = -1;
  1295. Slapi_Connection *conn;
  1296. Slapi_Operation *op;
  1297. int reverse_list = 0;
  1298. slapi_pblock_get(pb, SLAPI_SEARCH_TARGET_SDN, &basesdn);
  1299. if (NULL == basesdn) {
  1300. slapi_send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL,
  1301. "Null target DN", 0, NULL);
  1302. return (-1);
  1303. }
  1304. slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
  1305. if (NULL == sr) {
  1306. goto bail;
  1307. }
  1308. slapi_pblock_get(pb, SLAPI_BACKEND, &be);
  1309. slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &li);
  1310. slapi_pblock_get(pb, SLAPI_SEARCH_SCOPE, &scope);
  1311. slapi_pblock_get(pb, SLAPI_MANAGEDSAIT, &managedsait);
  1312. slapi_pblock_get(pb, SLAPI_SEARCH_FILTER, &filter);
  1313. slapi_pblock_get(pb, SLAPI_NENTRIES, &nentries);
  1314. slapi_pblock_get(pb, SLAPI_SEARCH_SIZELIMIT, &slimit);
  1315. slapi_pblock_get(pb, SLAPI_SEARCH_TIMELIMIT, &tlimit);
  1316. slapi_pblock_get(pb, SLAPI_REQUESTOR_ISROOT, &isroot);
  1317. slapi_pblock_get(pb, SLAPI_SEARCH_REFERRALS, &urls);
  1318. slapi_pblock_get(pb, SLAPI_TARGET_UNIQUEID, &target_uniqueid);
  1319. slapi_pblock_get(pb, SLAPI_TXN, &txn.back_txn_txn);
  1320. slapi_pblock_get(pb, SLAPI_CONNECTION, &conn);
  1321. slapi_pblock_get(pb, SLAPI_OPERATION, &op);
  1322. if ((reverse_list = operation_is_flag_set(op, OP_FLAG_REVERSE_CANDIDATE_ORDER))) {
  1323. /*
  1324. * Start at the end of the list and work our way forward. Since a single
  1325. * search can enter this function multiple times, we need to keep track
  1326. * of our state, and only initialize sr_current once.
  1327. */
  1328. if (!op->o_reverse_search_state && sr->sr_candidates) {
  1329. sr->sr_current = sr->sr_candidates->b_nids;
  1330. op->o_reverse_search_state = REV_STARTED;
  1331. }
  1332. }
  1333. if (!txn.back_txn_txn) {
  1334. dblayer_txn_init(li, &txn);
  1335. slapi_pblock_set(pb, SLAPI_TXN, txn.back_txn_txn);
  1336. }
  1337. if (sr->sr_norm_filter) {
  1338. int val = 1;
  1339. slapi_pblock_set(pb, SLAPI_PLUGIN_SYNTAX_FILTER_NORMALIZED, &val);
  1340. filter = sr->sr_norm_filter;
  1341. }
  1342. if (op_is_pagedresults(op)) {
  1343. int myslimit;
  1344. /* On Simple Paged Results search, sizelimit is appied for each page. */
  1345. slapi_pblock_get(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx);
  1346. myslimit = pagedresults_get_sizelimit(conn, op, pr_idx);
  1347. if (myslimit >= 0) {
  1348. slimit = myslimit;
  1349. }
  1350. } else if (sr->sr_current_sizelimit >= 0) {
  1351. /*
  1352. * sr_current_sizelimit contains the current sizelimit.
  1353. * In case of paged results, getting one page is one operation,
  1354. * while the results on each page are from same back_search_result_set.
  1355. * To maintain sizelimit beyond operations, back_search_result_set
  1356. * holds the current sizelimit value.
  1357. * (The current sizelimit is valid inside an operation, as well.)
  1358. */
  1359. slimit = sr->sr_current_sizelimit;
  1360. }
  1361. inst = (ldbm_instance *)be->be_instance_info;
  1362. /* Return to the cache the entry we handed out last time */
  1363. /* If we are using the extension, the front end will tell
  1364. * us when to do this so we don't do it now */
  1365. if (sr->sr_entry) {
  1366. non_target_cache_return(op, &inst->inst_cache, &(sr->sr_entry));
  1367. sr->sr_entry = NULL;
  1368. }
  1369. if (sr->sr_vlventry != NULL) {
  1370. /* This empty entry was handed out last time because the ACL check failed on a VLV Search.
  1371. * The empty entry has a pointer to the cache entry dn... make sure we don't free the dn
  1372. * which belongs to the cache entry. */
  1373. slapi_entry_free(sr->sr_vlventry);
  1374. sr->sr_vlventry = NULL;
  1375. }
  1376. slapi_operation_time_expiry(op, (time_t)tlimit, &expire_time);
  1377. llimit = sr->sr_lookthroughlimit;
  1378. /* Find the next candidate entry and return it. */
  1379. while (1) {
  1380. if (li->li_dblock_monitoring &&
  1381. slapi_atomic_load_32((int32_t *)&(li->li_dblock_threshold_reached), __ATOMIC_RELAXED)) {
  1382. slapi_log_err(SLAPI_LOG_CRIT, "ldbm_back_next_search_entry",
  1383. "DB locks threshold is reached (nsslapd-db-locks-monitoring-threshold "
  1384. "under cn=bdb,cn=config,cn=ldbm database,cn=plugins,cn=config). "
  1385. "Please, increase nsslapd-db-locks according to your needs.\n");
  1386. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, NULL);
  1387. delete_search_result_set(pb, &sr);
  1388. rc = SLAPI_FAIL_GENERAL;
  1389. slapi_send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "DB locks threshold is reached (nsslapd-db-locks-monitoring-threshold)", 0, NULL);
  1390. goto bail;
  1391. }
  1392. /* check for abandon */
  1393. if (slapi_op_abandoned(pb) || (NULL == sr)) {
  1394. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate);
  1395. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, NULL);
  1396. delete_search_result_set(pb, &sr);
  1397. rc = SLAPI_FAIL_GENERAL;
  1398. goto bail;
  1399. }
  1400. /*
  1401. * Check time limit, Check this only every few iters to prevent smashing the clock api?
  1402. */
  1403. if (slapi_timespec_expire_check(&expire_time) == TIMER_EXPIRED) {
  1404. slapi_log_err(SLAPI_LOG_TRACE, "ldbm_back_next_search_entry", "LDAP_TIMELIMIT_EXCEEDED\n");
  1405. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate);
  1406. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, NULL);
  1407. delete_search_result_set(pb, &sr);
  1408. rc = SLAPI_FAIL_GENERAL;
  1409. slapi_send_ldap_result(pb, LDAP_TIMELIMIT_EXCEEDED, NULL, NULL, nentries, urls);
  1410. goto bail;
  1411. }
  1412. /* check lookthrough limit */
  1413. if (llimit != -1 && sr->sr_lookthroughcount >= llimit) {
  1414. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate);
  1415. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, NULL);
  1416. delete_search_result_set(pb, &sr);
  1417. rc = SLAPI_FAIL_GENERAL;
  1418. slapi_send_ldap_result(pb, LDAP_ADMINLIMIT_EXCEEDED, NULL, NULL, nentries, urls);
  1419. goto bail;
  1420. }
  1421. /*
  1422. * Get the entry ID
  1423. */
  1424. if (reverse_list) {
  1425. /*
  1426. * This is probably a tombstone reaping, we need to process in the candidate
  1427. * list in reserve order, or else we can orphan tombstone entries by removing
  1428. * it's parent tombstone entry first.
  1429. */
  1430. id = idl_iterator_dereference_decrement(&(sr->sr_current), sr->sr_candidates);
  1431. if ((sr->sr_current == 0) && op->o_reverse_search_state != LAST_REV_ENTRY) {
  1432. /*
  1433. * We hit the last entry and we need to process it, but the decrement
  1434. * function will keep returning the last entry. So we need to mark that
  1435. * we have hit the last entry so we know to stop on the next pass.
  1436. */
  1437. op->o_reverse_search_state = LAST_REV_ENTRY;
  1438. } else if (op->o_reverse_search_state == LAST_REV_ENTRY) {
  1439. /* we're done */
  1440. id = NOID;
  1441. }
  1442. } else {
  1443. /* Process the candidate list in the normal order. */
  1444. id = idl_iterator_dereference_increment(&(sr->sr_current), sr->sr_candidates);
  1445. }
  1446. if (id == NOID) {
  1447. /* No more entries */
  1448. /* destroy back_search_result_set */
  1449. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate);
  1450. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, NULL);
  1451. delete_search_result_set(pb, &sr);
  1452. op->o_reverse_search_state = 0;
  1453. rc = 0;
  1454. goto bail;
  1455. }
  1456. ++sr->sr_lookthroughcount; /* checked above */
  1457. /* Make sure the backend is available */
  1458. if (be->be_state != BE_STATE_STARTED) {
  1459. slapi_send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL,
  1460. "Backend is stopped", 0, NULL);
  1461. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, NULL);
  1462. delete_search_result_set(pb, &sr);
  1463. rc = SLAPI_FAIL_GENERAL;
  1464. goto bail;
  1465. }
  1466. /* get the entry */
  1467. e = operation_get_target_entry(op);
  1468. if ((e == NULL) || (id != operation_get_target_entry_id(op))) {
  1469. /* if the entry is not the target_entry (base search)
  1470. * we need to fetch it from the entry cache (it was not
  1471. * referenced in the operation) */
  1472. e = id2entry(be, id, &txn, &err);
  1473. }
  1474. if (e == NULL) {
  1475. if (err != 0 && err != DBI_RC_NOTFOUND) {
  1476. slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_next_search_entry",
  1477. "next_search_entry db err %d\n", err);
  1478. if (LDBM_OS_ERR_IS_DISKFULL(err)) {
  1479. /* disk full in the middle of returning search results
  1480. * is gonna be traumatic. unavoidable. */
  1481. slapi_send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL, NULL, 0, NULL);
  1482. rc = return_on_disk_full(li);
  1483. goto bail;
  1484. }
  1485. }
  1486. slapi_log_err(SLAPI_LOG_ARGS, "ldbm_back_next_search_entry", "candidate %lu not found\n",
  1487. (u_long)id);
  1488. if (err == DBI_RC_NOTFOUND) {
  1489. /* Since we didn't really look at this entry, we should
  1490. * decrement the lookthrough counter (it was just incremented).
  1491. * If we didn't do this, it would be possible to go over the
  1492. * lookthrough limit when there are fewer entries in the database
  1493. * than the lookthrough limit. This could happen on an ALLIDS
  1494. * search after adding a bunch of entries and then deleting them. */
  1495. --sr->sr_lookthroughcount;
  1496. }
  1497. continue;
  1498. }
  1499. e->ep_vlventry = NULL;
  1500. sr->sr_entry = e;
  1501. /*
  1502. * If it's a referral, return it without checking the
  1503. * filter explicitly here since it's only a candidate anyway. Do
  1504. * check the scope though.
  1505. */
  1506. if (!managedsait && slapi_entry_attr_find(e->ep_entry, "ref", &attr) == 0) {
  1507. Slapi_Value **refs = attr_get_present_values(attr);
  1508. if (refs == NULL || refs[0] == NULL) {
  1509. slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_next_search_entry", "null ref in (%s)\n",
  1510. backentry_get_ndn(e));
  1511. } else if (slapi_sdn_scope_test(backentry_get_sdn(e), basesdn, scope)) {
  1512. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, e->ep_entry);
  1513. rc = 0;
  1514. goto bail;
  1515. }
  1516. } else {
  1517. /*
  1518. * As per slapi_filter_test:
  1519. * 0 filter matched
  1520. * -1 filter did not match
  1521. * >0 an ldap error code
  1522. */
  1523. int filter_test = -1;
  1524. int is_bulk_import = operation_is_flag_set(op, OP_FLAG_BULK_IMPORT);
  1525. if (is_bulk_import) {
  1526. /* If it is from bulk import, no need to check. */
  1527. filter_test = 0;
  1528. slimit = -1; /* no sizelimit applied */
  1529. } else if ((slapi_entry_flag_is_set(e->ep_entry, SLAPI_ENTRY_LDAPSUBENTRY) &&
  1530. !filter_flag_is_set(filter, SLAPI_FILTER_LDAPSUBENTRY)) ||
  1531. (slapi_entry_flag_is_set(e->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE) &&
  1532. ((!isroot && !filter_flag_is_set(filter, SLAPI_FILTER_RUV)) ||
  1533. !filter_flag_is_set(filter, SLAPI_FILTER_TOMBSTONE))))
  1534. {
  1535. /* If the entry is an LDAP subentry and filter don't filter subentries OR
  1536. * the entry is a TombStone and filter don't filter Tombstone
  1537. * don't return the entry. We make a special case to allow a non-root user
  1538. * to search for the RUV entry using a filter of:
  1539. *
  1540. * "(&(objectclass=nstombstone)(nsuniqueid=ffffffff-ffffffff-ffffffff-ffffffff))"
  1541. *
  1542. * For this RUV case, we let the ACL check apply.
  1543. */
  1544. /* ugaston - we don't want to mistake this filter failure with the one below due to ACL,
  1545. * because whereas the former should be read as 'no entry must be returned', the latter
  1546. * might still lead to return an empty entry. */
  1547. filter_test = -1;
  1548. } else {
  1549. /* it's a regular entry, check if it matches the filter, and passes the ACL check */
  1550. if (0 != (sr->sr_flags & SR_FLAG_CAN_SKIP_FILTER_TEST)) {
  1551. /* Since we do access control checking in the filter test (?Why?) we need to check access now */
  1552. slapi_log_err(SLAPI_LOG_FILTER, "ldbm_back_next_search_entry",
  1553. "Bypassing filter test\n");
  1554. if (ACL_CHECK_FLAG) {
  1555. filter_test = slapi_vattr_filter_test_ext(pb, e->ep_entry, filter, ACL_CHECK_FLAG, 1 /* Only perform access checking, thank you */);
  1556. } else {
  1557. filter_test = 0;
  1558. }
  1559. if (li->li_filter_bypass_check) {
  1560. int ft_rc;
  1561. slapi_log_err(SLAPI_LOG_FILTER, "ldbm_back_next_search_entry", "Checking bypass\n");
  1562. ft_rc = slapi_vattr_filter_test(pb, e->ep_entry, filter,
  1563. ACL_CHECK_FLAG);
  1564. if (filter_test != ft_rc) {
  1565. /* Oops ! This means that we thought we could bypass the filter test, but noooo... */
  1566. slapi_log_err(SLAPI_LOG_ERR, "ldbm_back_next_search_entry",
  1567. "Filter bypass ERROR on entry %s\n", backentry_get_ndn(e));
  1568. filter_test = ft_rc; /* Fix the error */
  1569. }
  1570. }
  1571. } else {
  1572. /* Old-style case---we need to do a filter test */
  1573. filter_test = slapi_vattr_filter_test(pb, e->ep_entry, filter, ACL_CHECK_FLAG);
  1574. }
  1575. }
  1576. if ((filter_test == 0) || (sr->sr_virtuallistview && (filter_test != -1)))
  1577. /* ugaston - if filter failed due to subentries or tombstones (filter_test=-1),
  1578. * just forget about it, since we don't want to return anything at all. */
  1579. {
  1580. if (is_bulk_import ||
  1581. slapi_uniqueIDCompareString(target_uniqueid, e->ep_entry->e_uniqueid) ||
  1582. slapi_sdn_scope_test_ext(backentry_get_sdn(e), basesdn, scope, e->ep_entry->e_flags)) {
  1583. /* check size limit */
  1584. if (slimit >= 0) {
  1585. if (--slimit < 0) {
  1586. non_target_cache_return(op, &inst->inst_cache, &e);
  1587. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate);
  1588. delete_search_result_set(pb, &sr);
  1589. slapi_send_ldap_result(pb, LDAP_SIZELIMIT_EXCEEDED, NULL, NULL, nentries, urls);
  1590. rc = SLAPI_FAIL_GENERAL;
  1591. goto bail;
  1592. }
  1593. slapi_pblock_set(pb, SLAPI_SEARCH_SIZELIMIT, &slimit);
  1594. if (op_is_pagedresults(op)) {
  1595. /*
  1596. * On Simple Paged Results search,
  1597. * sizelimit is appied to each page.
  1598. */
  1599. pagedresults_set_sizelimit(conn, op, slimit, pr_idx);
  1600. }
  1601. sr->sr_current_sizelimit = slimit;
  1602. }
  1603. if ((filter_test != 0) && sr->sr_virtuallistview) {
  1604. /* Slapi Filter Test failed.
  1605. * Must be that the ACL check failed.
  1606. * Send back an empty entry.
  1607. */
  1608. sr->sr_vlventry = slapi_entry_alloc();
  1609. slapi_entry_init(sr->sr_vlventry, slapi_ch_strdup(slapi_entry_get_dn_const(e->ep_entry)), NULL);
  1610. e->ep_vlventry = sr->sr_vlventry;
  1611. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, sr->sr_vlventry);
  1612. } else {
  1613. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, e->ep_entry);
  1614. }
  1615. rc = 0;
  1616. goto bail;
  1617. } else {
  1618. non_target_cache_return(op, &inst->inst_cache, &(sr->sr_entry));
  1619. sr->sr_entry = NULL;
  1620. }
  1621. } else {
  1622. /* Failed the filter test, and this isn't a VLV Search */
  1623. non_target_cache_return(op, &inst->inst_cache, &(sr->sr_entry));
  1624. sr->sr_entry = NULL;
  1625. if (LDAP_UNWILLING_TO_PERFORM == filter_test) {
  1626. /* Need to catch this error to detect the vattr loop */
  1627. slapi_send_ldap_result(pb, filter_test, NULL,
  1628. "Failed the filter test", 0, NULL);
  1629. rc = SLAPI_FAIL_GENERAL;
  1630. goto bail;
  1631. } else if (LDAP_TIMELIMIT_EXCEEDED == filter_test) {
  1632. slapi_send_ldap_result(pb, LDAP_TIMELIMIT_EXCEEDED, NULL, NULL, nentries, urls);
  1633. rc = SLAPI_FAIL_GENERAL;
  1634. goto bail;
  1635. }
  1636. }
  1637. }
  1638. }
  1639. /* check for the final abandon */
  1640. if (slapi_op_abandoned(pb)) {
  1641. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate);
  1642. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, NULL);
  1643. delete_search_result_set(pb, &sr);
  1644. rc = SLAPI_FAIL_GENERAL;
  1645. }
  1646. bail:
  1647. if (rc && op) {
  1648. op->o_reverse_search_state = 0;
  1649. }
  1650. return rc;
  1651. }
  1652. /*
  1653. * Move back the current position in the search result set by one.
  1654. * Paged Results needs to read ahead one entry to catch the end of the search
  1655. * result set at the last entry not to show the prompt when there is no more
  1656. * entries.
  1657. */
  1658. void
  1659. ldbm_back_prev_search_results(Slapi_PBlock *pb)
  1660. {
  1661. backend *be;
  1662. ldbm_instance *inst;
  1663. back_search_result_set *sr;
  1664. slapi_pblock_get(pb, SLAPI_BACKEND, &be);
  1665. if (!be) {
  1666. slapi_log_err(SLAPI_LOG_ERR,
  1667. "ldbm_back_prev_search_results", "no backend\n");
  1668. return;
  1669. }
  1670. inst = (ldbm_instance *)be->be_instance_info;
  1671. if (!inst) {
  1672. slapi_log_err(SLAPI_LOG_ERR,
  1673. "ldbm_back_prev_search_results", "no backend instance\n");
  1674. return;
  1675. }
  1676. slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
  1677. if (sr) {
  1678. if (sr->sr_entry) {
  1679. /* The last entry should be returned to cache */
  1680. slapi_log_err(SLAPI_LOG_BACKLDBM,
  1681. "ldbm_back_prev_search_results", "returning: %s\n",
  1682. slapi_entry_get_dn_const(sr->sr_entry->ep_entry));
  1683. CACHE_RETURN(&inst->inst_cache, &(sr->sr_entry));
  1684. sr->sr_entry = NULL;
  1685. }
  1686. idl_iterator_decrement(&(sr->sr_current));
  1687. --sr->sr_lookthroughcount;
  1688. }
  1689. return;
  1690. }
  1691. static back_search_result_set *
  1692. new_search_result_set(IDList *idl, int vlv, int lookthroughlimit)
  1693. {
  1694. back_search_result_set *p = (back_search_result_set *)slapi_ch_calloc(1, sizeof(back_search_result_set));
  1695. p->sr_candidates = idl;
  1696. p->sr_current = idl_iterator_init(idl);
  1697. p->sr_lookthroughlimit = lookthroughlimit;
  1698. p->sr_virtuallistview = vlv;
  1699. p->sr_current_sizelimit = -1;
  1700. return p;
  1701. }
  1702. static void
  1703. delete_search_result_set(Slapi_PBlock *pb, back_search_result_set **sr)
  1704. {
  1705. int rc = 0, filt_errs = 0;
  1706. if (NULL == sr || NULL == *sr) {
  1707. return;
  1708. }
  1709. if (pb) {
  1710. Operation *pb_op = NULL;
  1711. slapi_pblock_get(pb, SLAPI_OPERATION, &pb_op);
  1712. if (op_is_pagedresults(pb_op)) {
  1713. /* If the op is pagedresults, let the module clean up sr. */
  1714. return;
  1715. }
  1716. pagedresults_set_search_result_pb(pb, NULL, 0);
  1717. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET, NULL);
  1718. }
  1719. if (NULL != (*sr)->sr_candidates) {
  1720. idl_free(&((*sr)->sr_candidates));
  1721. }
  1722. rc = slapi_filter_apply((*sr)->sr_norm_filter, ldbm_search_free_compiled_filter,
  1723. NULL, &filt_errs);
  1724. if (rc != SLAPI_FILTER_SCAN_NOMORE) {
  1725. slapi_log_err(SLAPI_LOG_ERR,
  1726. "delete_search_result_set", "Could not free the pre-compiled regexes in the search filter - error %d %d\n",
  1727. rc, filt_errs);
  1728. }
  1729. slapi_filter_free((*sr)->sr_norm_filter, 1);
  1730. memset(*sr, 0, sizeof(back_search_result_set));
  1731. slapi_ch_free((void **)sr);
  1732. return;
  1733. }
  1734. /*
  1735. * This function is called from pagedresults free/cleanup functions.
  1736. */
  1737. void
  1738. ldbm_back_search_results_release(void **sr)
  1739. {
  1740. /* passing NULL pb forces to delete the search result set */
  1741. delete_search_result_set(NULL, (back_search_result_set **)sr);
  1742. }
  1743. int
  1744. ldbm_back_entry_release(Slapi_PBlock *pb, void *backend_info_ptr)
  1745. {
  1746. backend *be;
  1747. ldbm_instance *inst;
  1748. if (backend_info_ptr == NULL) {
  1749. return 1;
  1750. }
  1751. slapi_pblock_get(pb, SLAPI_BACKEND, &be);
  1752. inst = (ldbm_instance *)be->be_instance_info;
  1753. if (((struct backentry *)backend_info_ptr)->ep_vlventry != NULL) {
  1754. /* This entry was created during a vlv search whose acl check failed.
  1755. * It needs to be freed here */
  1756. slapi_entry_free(((struct backentry *)backend_info_ptr)->ep_vlventry);
  1757. ((struct backentry *)backend_info_ptr)->ep_vlventry = NULL;
  1758. }
  1759. CACHE_RETURN(&inst->inst_cache, (struct backentry **)&backend_info_ptr);
  1760. return 0;
  1761. }