opshared.c 61 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757
  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. /* opshared.c - functions shared between regular and internal operations */
  13. #include "slap.h"
  14. #include "index_subsys.h"
  15. #define PAGEDRESULTS_PAGE_END 1
  16. #define PAGEDRESULTS_SEARCH_END 2
  17. /* helper functions */
  18. static void compute_limits (Slapi_PBlock *pb);
  19. /* attributes that no clients are allowed to add or modify */
  20. static char *protected_attrs_all [] = { PSEUDO_ATTR_UNHASHEDUSERPASSWORD,
  21. NULL };
  22. static char *pwpolicy_lock_attrs_all [] = { "passwordRetryCount",
  23. "retryCountResetTime",
  24. "accountUnlockTime",
  25. NULL};
  26. /* Forward declarations */
  27. static void compute_limits (Slapi_PBlock *pb);
  28. static int send_results_ext (Slapi_PBlock *pb, int send_result, int *nentries, int pagesize, unsigned int *pr_stat);
  29. static int process_entry(Slapi_PBlock *pb, Slapi_Entry *e, int send_result);
  30. int op_shared_is_allowed_attr (const char *attr_name, int replicated_op)
  31. {
  32. int i;
  33. slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
  34. /* ONREPL - should allow backends to plugin here to specify
  35. attributes that are not allowed */
  36. if (!replicated_op) {
  37. struct asyntaxinfo *asi;
  38. int no_user_mod = 0;
  39. /* check list of attributes that no client is allowed to specify */
  40. for (i = 0; protected_attrs_all[i]; i ++) {
  41. if (strcasecmp (attr_name, protected_attrs_all[i]) == 0) {
  42. /* this attribute is not allowed */
  43. return 0;
  44. }
  45. }
  46. /*
  47. * check to see if attribute is marked as one clients can't modify
  48. */
  49. asi = attr_syntax_get_by_name( attr_name, 0 );
  50. if ( NULL != asi &&
  51. 0 != ( asi->asi_flags & SLAPI_ATTR_FLAG_NOUSERMOD )) {
  52. /* this attribute is not allowed */
  53. no_user_mod = 1;
  54. }
  55. attr_syntax_return( asi );
  56. if ( no_user_mod ) {
  57. return( 0 );
  58. }
  59. } else if (!slapdFrontendConfig->pw_is_global_policy) {
  60. /* check list of password policy attributes for locking accounts */
  61. for (i = 0; pwpolicy_lock_attrs_all[i]; i ++)
  62. {
  63. if (strcasecmp (attr_name, pwpolicy_lock_attrs_all[i]) == 0)
  64. {
  65. /* this attribute is not allowed */
  66. return 0;
  67. }
  68. }
  69. }
  70. /* this attribute is ok */
  71. return 1;
  72. }
  73. static ps_service_fn_ptr ps_service_fn = NULL;
  74. void
  75. do_ps_service(Slapi_Entry *e, Slapi_Entry *eprev, ber_int_t chgtype, ber_int_t chgnum)
  76. {
  77. if (NULL == ps_service_fn) {
  78. if (get_entry_point(ENTRY_POINT_PS_SERVICE, (caddr_t *)(&ps_service_fn)) < 0) {
  79. return;
  80. }
  81. }
  82. (ps_service_fn)(e, eprev, chgtype, chgnum);
  83. }
  84. void
  85. modify_update_last_modified_attr(Slapi_PBlock *pb, Slapi_Mods *smods)
  86. {
  87. char buf[20];
  88. char *plugin_dn = NULL;
  89. char *binddn = NULL;
  90. struct berval bv;
  91. struct berval *bvals[2];
  92. time_t curtime;
  93. struct tm utm;
  94. Operation *op;
  95. struct slapdplugin *plugin = NULL;
  96. struct slapi_componentid *cid = NULL;
  97. slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
  98. LDAPDebug(LDAP_DEBUG_TRACE, "modify_update_last_modified_attr\n", 0, 0, 0);
  99. slapi_pblock_get(pb, SLAPI_OPERATION, &op);
  100. bvals[0] = &bv;
  101. bvals[1] = NULL;
  102. if(slapdFrontendConfig->plugin_track){
  103. /* plugin bindDN tracking is enabled, grab the bind dn from thread local storage */
  104. if(slapi_sdn_isempty(&op->o_sdn)){
  105. bv.bv_val = "";
  106. bv.bv_len = 0;
  107. } else {
  108. slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &cid);
  109. if (cid){
  110. plugin=(struct slapdplugin *) cid->sci_plugin;
  111. } else {
  112. slapi_pblock_get (pb, SLAPI_PLUGIN, &plugin);
  113. }
  114. if(plugin)
  115. plugin_dn = plugin_get_dn (plugin);
  116. if(plugin_dn){
  117. bv.bv_val = plugin_dn;
  118. bv.bv_len = strlen(bv.bv_val);
  119. } else {
  120. bv.bv_val = (char*)slapi_sdn_get_dn(&op->o_sdn);
  121. bv.bv_len = strlen(bv.bv_val);
  122. }
  123. }
  124. slapi_mods_add_modbvps(smods, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES,
  125. "internalModifiersName", bvals);
  126. slapi_ch_free_string(&plugin_dn);
  127. /* Grab the thread data(binddn) */
  128. slapi_td_get_dn(&binddn);
  129. if(binddn == NULL){
  130. /* anonymous bind */
  131. bv.bv_val = "";
  132. bv.bv_len = 0;
  133. } else {
  134. bv.bv_val = binddn;
  135. bv.bv_len = strlen(bv.bv_val);
  136. }
  137. } else {
  138. /* fill in modifiersname */
  139. if (slapi_sdn_isempty(&op->o_sdn)) {
  140. bv.bv_val = "";
  141. bv.bv_len = 0;
  142. } else {
  143. bv.bv_val = (char*)slapi_sdn_get_dn(&op->o_sdn);
  144. bv.bv_len = strlen(bv.bv_val);
  145. }
  146. }
  147. slapi_mods_add_modbvps(smods, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES,
  148. "modifiersname", bvals);
  149. /* fill in modifytimestamp */
  150. curtime = current_time();
  151. gmtime_r(&curtime, &utm);
  152. strftime(buf, sizeof(buf), "%Y%m%d%H%M%SZ", &utm);
  153. bv.bv_val = buf;
  154. bv.bv_len = strlen(bv.bv_val);
  155. slapi_mods_add_modbvps(smods, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES,
  156. "modifytimestamp", bvals);
  157. }
  158. /*
  159. * If the attribute is one of the last mod attributes return 1,
  160. * otherwise return 0;
  161. */
  162. int
  163. slapi_attr_is_last_mod(char *attr)
  164. {
  165. if(strcasecmp (attr, "modifytimestamp") == 0 ||
  166. strcasecmp (attr, "modifiersname") == 0 ||
  167. strcasecmp (attr, "internalmodifytimestamp") == 0 ||
  168. strcasecmp (attr, "internalmodifiersname") == 0)
  169. {
  170. return 1;
  171. }
  172. return 0;
  173. }
  174. /*
  175. * Returns: 0 - if the operation is successful
  176. * < 0 - if operation fails.
  177. * Note that an operation is considered "failed" if a result is sent
  178. * directly to the client when send_result is 0.
  179. */
  180. void
  181. op_shared_search (Slapi_PBlock *pb, int send_result)
  182. {
  183. char *base = NULL;
  184. const char *normbase = NULL;
  185. char *fstr;
  186. int scope;
  187. Slapi_Backend *be = NULL;
  188. Slapi_Backend *be_single = NULL;
  189. Slapi_Backend *be_list[BE_LIST_SIZE+1];
  190. Slapi_Entry *referral_list[BE_LIST_SIZE+1];
  191. char attrlistbuf[ 1024 ], *attrliststr, **attrs = NULL;
  192. int rc = 0;
  193. int internal_op;
  194. Slapi_DN *basesdn = NULL;
  195. Slapi_DN *sdn = NULL;
  196. Slapi_Operation *operation = NULL;
  197. Slapi_Entry *referral = NULL;
  198. char *proxydn = NULL;
  199. char *proxystr = NULL;
  200. int proxy_err = LDAP_SUCCESS;
  201. char *errtext = NULL;
  202. int nentries,pnentries;
  203. int flag_search_base_found = 0;
  204. int flag_no_such_object = 0;
  205. int flag_referral = 0;
  206. int flag_psearch = 0;
  207. int err_code = LDAP_SUCCESS;
  208. LDAPControl **ctrlp;
  209. struct berval *ctl_value = NULL;
  210. int iscritical = 0;
  211. char *be_name = NULL;
  212. int index = 0;
  213. int sent_result = 0;
  214. unsigned int pr_stat = 0;
  215. ber_int_t pagesize = -1;
  216. ber_int_t estimate = 0; /* estimated search result set size */
  217. int curr_search_count = 0;
  218. Slapi_Backend *pr_be = NULL;
  219. void *pr_search_result = NULL;
  220. int pr_idx = -1;
  221. Slapi_DN *orig_sdn = NULL;
  222. int free_sdn = 0;
  223. be_list[0] = NULL;
  224. referral_list[0] = NULL;
  225. /* get search parameters */
  226. slapi_pblock_get(pb, SLAPI_ORIGINAL_TARGET_DN, &base);
  227. slapi_pblock_get(pb, SLAPI_SEARCH_TARGET_SDN, &sdn);
  228. if (NULL == sdn) {
  229. sdn = slapi_sdn_new_dn_byval(base);
  230. slapi_pblock_set(pb, SLAPI_SEARCH_TARGET_SDN, sdn);
  231. free_sdn = 1;
  232. } else {
  233. /* save it so we can restore it later - may have to replace it internally
  234. e.g. for onelevel and subtree searches, but need to restore it */
  235. orig_sdn = sdn;
  236. }
  237. normbase = slapi_sdn_get_dn(sdn);
  238. if (base && (strlen(base) > 0) && (NULL == normbase)) {
  239. /* normalization failed */
  240. op_shared_log_error_access(pb, "SRCH", base, "invalid dn");
  241. send_ldap_result(pb, LDAP_INVALID_DN_SYNTAX, NULL, "invalid dn", 0, NULL);
  242. rc = -1;
  243. goto free_and_return_nolock;
  244. }
  245. basesdn = slapi_sdn_dup(sdn);
  246. slapi_pblock_get(pb, SLAPI_SEARCH_SCOPE, &scope);
  247. slapi_pblock_get(pb, SLAPI_SEARCH_STRFILTER, &fstr);
  248. slapi_pblock_get(pb, SLAPI_SEARCH_ATTRS, &attrs);
  249. slapi_pblock_get (pb, SLAPI_OPERATION, &operation);
  250. internal_op= operation_is_flag_set(operation, OP_FLAG_INTERNAL);
  251. flag_psearch = operation_is_flag_set(operation, OP_FLAG_PS);
  252. /* get the proxy auth dn if the proxy auth control is present */
  253. proxy_err = proxyauth_get_dn(pb, &proxydn, &errtext);
  254. if (operation_is_flag_set(operation,OP_FLAG_ACTION_LOG_ACCESS))
  255. {
  256. char *fmtstr;
  257. #define SLAPD_SEARCH_FMTSTR_BASE "conn=%" NSPRIu64 " op=%d SRCH base=\"%s\" scope=%d "
  258. #define SLAPD_SEARCH_FMTSTR_BASE_INT "conn=%s op=%d SRCH base=\"%s\" scope=%d "
  259. #define SLAPD_SEARCH_FMTSTR_REMAINDER " attrs=%s%s%s\n"
  260. PR_ASSERT(fstr);
  261. if ( strlen(fstr) > 1024 )
  262. {
  263. /*
  264. * slapi_log_access() throws away log lines that are longer than
  265. * 2048 characters, so we limit the filter string to 1024 (better
  266. * to log something rather than nothing)
  267. */
  268. if ( !internal_op )
  269. {
  270. fmtstr = SLAPD_SEARCH_FMTSTR_BASE "filter=\"%.1024s...\"" SLAPD_SEARCH_FMTSTR_REMAINDER;
  271. }
  272. else
  273. {
  274. fmtstr = SLAPD_SEARCH_FMTSTR_BASE_INT "filter=\"%.1024s...\"" SLAPD_SEARCH_FMTSTR_REMAINDER;
  275. }
  276. } else {
  277. if ( !internal_op )
  278. {
  279. fmtstr = SLAPD_SEARCH_FMTSTR_BASE "filter=\"%s\"" SLAPD_SEARCH_FMTSTR_REMAINDER;
  280. }
  281. else
  282. {
  283. fmtstr = SLAPD_SEARCH_FMTSTR_BASE_INT "filter=\"%s\"" SLAPD_SEARCH_FMTSTR_REMAINDER;
  284. }
  285. }
  286. if ( NULL == attrs ) {
  287. attrliststr = "ALL";
  288. } else {
  289. strarray2str( attrs, attrlistbuf, sizeof( attrlistbuf ),
  290. 1 /* include quotes */ );
  291. attrliststr = attrlistbuf;
  292. }
  293. if (proxydn)
  294. {
  295. proxystr = slapi_ch_smprintf(" authzid=\"%s\"", proxydn);
  296. }
  297. if ( !internal_op )
  298. {
  299. slapi_log_access(LDAP_DEBUG_STATS, fmtstr,
  300. pb->pb_conn->c_connid,
  301. pb->pb_op->o_opid,
  302. normbase,
  303. scope, fstr, attrliststr,
  304. flag_psearch ? " options=persistent" : "",
  305. proxystr ? proxystr : "");
  306. }
  307. else
  308. {
  309. slapi_log_access(LDAP_DEBUG_ARGS, fmtstr,
  310. LOG_INTERNAL_OP_CON_ID,
  311. LOG_INTERNAL_OP_OP_ID,
  312. normbase,
  313. scope, fstr, attrliststr,
  314. flag_psearch ? " options=persistent" : "",
  315. proxystr ? proxystr : "");
  316. }
  317. }
  318. /* If we encountered an error parsing the proxy control, return an error
  319. * to the client. We do this here to ensure that we log the operation first.
  320. */
  321. if (proxy_err != LDAP_SUCCESS)
  322. {
  323. rc = -1;
  324. send_ldap_result(pb, proxy_err, NULL, errtext, 0, NULL);
  325. goto free_and_return_nolock;
  326. }
  327. /* target spec is used to decide which plugins are applicable for
  328. * the operation. basesdn is duplicated and set to target spec.
  329. */
  330. operation_set_target_spec (pb->pb_op, basesdn);
  331. /*
  332. * this is time to check if mapping tree specific control was used to
  333. * specify that we want to parse only one backend.
  334. */
  335. slapi_pblock_get(pb, SLAPI_REQCONTROLS, &ctrlp);
  336. if (ctrlp)
  337. {
  338. if (slapi_control_present(ctrlp, MTN_CONTROL_USE_ONE_BACKEND_EXT_OID,
  339. &ctl_value, &iscritical))
  340. {
  341. /* this control is the smart version of MTN_CONTROL_USE_ONE_BACKEND_OID,
  342. * it works out for itself what back end is required (thereby relieving
  343. * the client of working out which backend it needs) by looking at the
  344. * base of the search if no value is supplied
  345. */
  346. if((ctl_value->bv_len != 0) && ctl_value->bv_val)
  347. {
  348. be_name = ctl_value->bv_val;
  349. }
  350. else
  351. {
  352. /* we don't need no steenkin values */
  353. Slapi_Backend *searchbe = slapi_be_select( sdn );
  354. if(searchbe && searchbe != defbackend_get_backend())
  355. {
  356. be_name = slapi_be_get_name(searchbe);
  357. }
  358. }
  359. }
  360. else
  361. {
  362. if (slapi_control_present(ctrlp, MTN_CONTROL_USE_ONE_BACKEND_OID,
  363. &ctl_value, &iscritical))
  364. {
  365. if ((ctl_value->bv_len == 0) || (ctl_value->bv_val == NULL))
  366. {
  367. rc = -1;
  368. if (iscritical)
  369. send_ldap_result(pb, LDAP_UNAVAILABLE_CRITICAL_EXTENSION, NULL, NULL, 0, NULL);
  370. else
  371. send_ldap_result(pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0, NULL);
  372. goto free_and_return_nolock;
  373. }
  374. else
  375. {
  376. be_name = ctl_value->bv_val;
  377. if (be_name == NULL)
  378. {
  379. rc = -1;
  380. if (iscritical)
  381. send_ldap_result(pb, LDAP_UNAVAILABLE_CRITICAL_EXTENSION, NULL, NULL, 0, NULL);
  382. else
  383. send_ldap_result(pb, LDAP_PROTOCOL_ERROR, NULL, NULL, 0, NULL);
  384. goto free_and_return_nolock;
  385. }
  386. }
  387. }
  388. }
  389. }
  390. if (be_name == NULL) {
  391. char errorbuf[SLAPI_DSE_RETURNTEXT_SIZE];
  392. /* no specific backend was requested, use the mapping tree
  393. */
  394. errorbuf[0] = '\0';
  395. err_code = slapi_mapping_tree_select_all(pb, be_list, referral_list, errorbuf, sizeof(errorbuf));
  396. if (((err_code != LDAP_SUCCESS) && (err_code != LDAP_OPERATIONS_ERROR) && (err_code != LDAP_REFERRAL))
  397. || ((err_code == LDAP_OPERATIONS_ERROR) && (be_list[0] == NULL))) {
  398. send_ldap_result(pb, err_code, NULL, errorbuf, 0, NULL);
  399. rc = -1;
  400. goto free_and_return;
  401. }
  402. if (be_list[0] != NULL) {
  403. index = 0;
  404. while (be_list[index] && be_list[index+1]) {
  405. index++;
  406. }
  407. be = be_list[index];
  408. } else {
  409. be = NULL;
  410. }
  411. } else {
  412. /* specific backend be_name was requested, use slapi_be_select_by_instance_name
  413. */
  414. be_single = be = slapi_be_select_by_instance_name(be_name);
  415. if (be_single) {
  416. slapi_be_Rlock(be_single);
  417. }
  418. be_list[0] = NULL;
  419. referral_list[0] = NULL;
  420. referral = NULL;
  421. }
  422. /* Handle the rest of the controls. */
  423. if (ctrlp)
  424. {
  425. if ( slapi_control_present (ctrlp, LDAP_CONTROL_GET_EFFECTIVE_RIGHTS,
  426. &ctl_value, &iscritical) )
  427. {
  428. operation->o_flags |= OP_FLAG_GET_EFFECTIVE_RIGHTS;
  429. }
  430. if ( slapi_control_present (ctrlp, LDAP_CONTROL_PAGEDRESULTS,
  431. &ctl_value, &iscritical) )
  432. {
  433. int pr_cookie = -1;
  434. /* be is set only when this request is new. otherwise, prev be is honored. */
  435. rc = pagedresults_parse_control_value(pb, ctl_value, &pagesize, &pr_idx, be);
  436. /* Let's set pr_idx even if it fails; in case, pr_idx == -1. */
  437. slapi_pblock_set(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx);
  438. slapi_pblock_set(pb, SLAPI_PAGED_RESULTS_COOKIE, &pr_cookie);
  439. if ((LDAP_SUCCESS == rc) || (LDAP_CANCELLED == rc) || (0 == pagesize)) {
  440. unsigned int opnote = SLAPI_OP_NOTE_SIMPLEPAGED;
  441. op_set_pagedresults(operation);
  442. pr_be = pagedresults_get_current_be(pb->pb_conn, pr_idx);
  443. if (be_name) {
  444. if (pr_be != be_single) {
  445. slapi_be_Unlock(be_single);
  446. be_single = be = pr_be;
  447. slapi_be_Rlock(be_single);
  448. }
  449. } else if (be_list[0]) {
  450. if (pr_be) { /* PAGED RESULT: be is found from the previous paging. */
  451. /* move the index in the be_list which matches pr_be */
  452. index = 0;
  453. while (be_list[index] && be_list[index+1] && pr_be != be_list[index]) {
  454. index++;
  455. }
  456. be = be_list[index];
  457. }
  458. }
  459. pr_search_result = pagedresults_get_search_result(pb->pb_conn, operation, 0/*not locked*/, pr_idx);
  460. estimate = pagedresults_get_search_result_set_size_estimate(pb->pb_conn, operation, pr_idx);
  461. if (pagedresults_get_unindexed(pb->pb_conn, operation, pr_idx)) {
  462. opnote |= SLAPI_OP_NOTE_UNINDEXED;
  463. }
  464. slapi_pblock_set( pb, SLAPI_OPERATION_NOTES, &opnote );
  465. if ((LDAP_CANCELLED == rc) || (0 == pagesize)) {
  466. /* paged-results-request was abandoned; making an empty cookie. */
  467. pagedresults_set_response_control(pb, 0, estimate, -1, pr_idx);
  468. send_ldap_result(pb, 0, NULL,
  469. "Simple Paged Results Search abandoned",
  470. 0, NULL);
  471. rc = LDAP_SUCCESS;
  472. goto free_and_return;
  473. }
  474. } else if (LDAP_UNWILLING_TO_PERFORM == rc) {
  475. send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL,
  476. "Simple Paged Results Search exceeded administration limit",
  477. 0, NULL);
  478. goto free_and_return;
  479. } else {
  480. /* parse paged-results-control failed */
  481. if (iscritical) { /* return an error since it's critical */
  482. send_ldap_result(pb, LDAP_UNAVAILABLE_CRITICAL_EXTENSION, NULL,
  483. "Simple Paged Results Search failed",
  484. 0, NULL);
  485. goto free_and_return;
  486. }
  487. }
  488. }
  489. }
  490. slapi_pblock_set(pb, SLAPI_BACKEND_COUNT, &index);
  491. if (be)
  492. {
  493. slapi_pblock_set(pb, SLAPI_BACKEND, be);
  494. /* adjust time and size limits */
  495. compute_limits (pb);
  496. /* set the timelimit to clean up the too-long-lived-paged results requests */
  497. if (op_is_pagedresults(operation)) {
  498. time_t optime, time_up;
  499. int tlimit;
  500. slapi_pblock_get( pb, SLAPI_SEARCH_TIMELIMIT, &tlimit );
  501. slapi_pblock_get( pb, SLAPI_OPINITIATED_TIME, &optime );
  502. time_up = (tlimit==-1 ? -1 : optime + tlimit); /* -1: no time limit */
  503. pagedresults_set_timelimit(pb->pb_conn, pb->pb_op, time_up, pr_idx);
  504. }
  505. /*
  506. * call the pre-search plugins. if they succeed, call the backend
  507. * search function. then call the post-search plugins.
  508. */
  509. /* ONREPL - should regular plugin be called for internal searches ? */
  510. if (plugin_call_plugins(pb, SLAPI_PLUGIN_PRE_SEARCH_FN) == 0)
  511. {
  512. slapi_pblock_set(pb, SLAPI_PLUGIN, be->be_database);
  513. set_db_default_result_handlers(pb);
  514. /* Now would be a good time to call the search rewriters for computed attrs */
  515. rc = compute_rewrite_search_filter(pb);
  516. switch (rc)
  517. {
  518. case 1: /* A rewriter says that we should refuse to perform this search.
  519. The potential exists that we will refuse to perform a search
  520. which we were going to refer, perhaps to a server which would
  521. be willing to perform the search. That's bad. The rewriter
  522. could be clever enough to spot this and do the right thing though. */
  523. send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "Search not supported", 0, NULL);
  524. rc = -1;
  525. goto free_and_return;
  526. case -2: /* memory was allocated */
  527. /* take note of any changes */
  528. slapi_pblock_get(pb, SLAPI_SEARCH_TARGET_SDN, &sdn);
  529. slapi_pblock_get(pb, SLAPI_SEARCH_SCOPE, &scope);
  530. if (NULL == sdn) {
  531. send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL,
  532. "target dn is lost", 0, NULL);
  533. rc = -1;
  534. goto free_and_return;
  535. }
  536. if (slapi_sdn_compare(basesdn, sdn)) {
  537. slapi_sdn_free(&basesdn);
  538. basesdn = operation_get_target_spec(pb->pb_op);
  539. slapi_sdn_free(&basesdn);
  540. basesdn = slapi_sdn_dup(sdn);
  541. operation_set_target_spec (pb->pb_op, basesdn);
  542. }
  543. break;
  544. case -1:
  545. case 0: /* OK */
  546. break;
  547. case 2: /* Operations error */
  548. send_ldap_result(pb, LDAP_OPERATIONS_ERROR, NULL, "search rewriter", 0, NULL);
  549. rc = -1;
  550. goto free_and_return;
  551. }
  552. } else {
  553. /*
  554. * A pre-operation plugin handled this search. Grab the return code
  555. * (it may have been set by a plugin) and return.
  556. *
  557. * In DS 5.x, the following two lines of code did not exist, which
  558. * means a pre-search function might return a non-zero value (which
  559. * indicates that a result was returned to the client) but the code
  560. * below would execute the search anyway. This was a regression from
  561. * the documented plugin API behavior (and from DS 3.x and 4.x).
  562. */
  563. slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &rc);
  564. goto free_and_return;
  565. }
  566. }
  567. /* PAR: now filters have been rewritten, we can assign plugins to work on them */
  568. index_subsys_assign_filter_decoders(pb);
  569. nentries = 0;
  570. rc = -1; /* zero backends would mean failure */
  571. while (be)
  572. {
  573. const Slapi_DN *be_suffix;
  574. int err = 0;
  575. Slapi_Backend *next_be = NULL;
  576. if (be->be_search == NULL)
  577. {
  578. send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "Function not implemented", 0, NULL);
  579. rc = -1;
  580. goto free_and_return;
  581. }
  582. pnentries = 0;
  583. /* the backends returns no such object when a
  584. * search is attempted in a node above their nsslapd-suffix
  585. * this is correct but a bit annoying when a backends
  586. * is below another backend because in that case the
  587. * such searches should sometimes succeed
  588. * To allow this we therefore have to change the
  589. * SLAPI_SEARCH_TARGET_SDN parameter in the pblock
  590. *
  591. * Also when we climb down the mapping tree we have to
  592. * change ONE-LEVEL searches to BASE
  593. */
  594. /* that means we only support one suffix per backend */
  595. be_suffix = slapi_be_getsuffix(be, 0);
  596. if (be_list[0] == NULL)
  597. {
  598. next_be = NULL;
  599. }
  600. else
  601. {
  602. index--;
  603. if (index>=0)
  604. next_be = be_list[index];
  605. else
  606. next_be = NULL;
  607. }
  608. if (op_is_pagedresults(operation) && pr_search_result) {
  609. void *sr = NULL;
  610. /* PAGED RESULTS and already have the search results from the prev op */
  611. pagedresults_lock(pb->pb_conn, pr_idx);
  612. /*
  613. * In async paged result case, the search result might be released
  614. * by other theads. We need to double check it in the locked region.
  615. */
  616. PR_EnterMonitor(pb->pb_conn->c_mutex);
  617. pr_search_result = pagedresults_get_search_result(pb->pb_conn, operation, 1/*locked*/, pr_idx);
  618. if (pr_search_result) {
  619. if (pagedresults_is_abandoned_or_notavailable(pb->pb_conn, 1/*locked*/, pr_idx)) {
  620. pagedresults_unlock(pb->pb_conn, pr_idx);
  621. /* Previous operation was abandoned and the simplepaged object is not in use. */
  622. send_ldap_result(pb, 0, NULL, "Simple Paged Results Search abandoned", 0, NULL);
  623. rc = LDAP_SUCCESS;
  624. PR_ExitMonitor(pb->pb_conn->c_mutex);
  625. goto free_and_return;
  626. } else {
  627. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, pr_search_result );
  628. rc = send_results_ext (pb, 1, &pnentries, pagesize, &pr_stat);
  629. /* search result could be reset in the backend/dse */
  630. slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
  631. pagedresults_set_search_result(pb->pb_conn, operation, sr, 1/*locked*/, pr_idx);
  632. PR_ExitMonitor(pb->pb_conn->c_mutex);
  633. }
  634. } else {
  635. pr_stat = PAGEDRESULTS_SEARCH_END;
  636. }
  637. pagedresults_unlock(pb->pb_conn, pr_idx);
  638. if ((PAGEDRESULTS_SEARCH_END == pr_stat) || (0 == pnentries)) {
  639. /* no more entries to send in the backend */
  640. if (NULL == next_be) {
  641. /* no more entries && no more backends */
  642. curr_search_count = -1;
  643. } else {
  644. curr_search_count = pnentries;
  645. }
  646. estimate = 0;
  647. pr_stat = PAGEDRESULTS_SEARCH_END; /* make sure stat is SEARCH_END */
  648. } else {
  649. curr_search_count = pnentries;
  650. estimate -= estimate?curr_search_count:0;
  651. }
  652. pagedresults_set_response_control(pb, 0, estimate,
  653. curr_search_count, pr_idx);
  654. if (pagedresults_get_with_sort(pb->pb_conn, operation, pr_idx)) {
  655. sort_make_sort_response_control(pb, CONN_GET_SORT_RESULT_CODE, NULL);
  656. }
  657. pagedresults_set_search_result_set_size_estimate(pb->pb_conn,
  658. operation,
  659. estimate, pr_idx);
  660. if (PAGEDRESULTS_SEARCH_END == pr_stat) {
  661. pagedresults_lock(pb->pb_conn, pr_idx);
  662. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET, NULL);
  663. if (!pagedresults_is_abandoned_or_notavailable(pb->pb_conn, 0/*not locked*/, pr_idx)) {
  664. pagedresults_free_one(pb->pb_conn, operation, pr_idx);
  665. }
  666. pagedresults_unlock(pb->pb_conn, pr_idx);
  667. if (next_be) {
  668. /* no more entries, but at least another backend */
  669. if (pagedresults_set_current_be(pb->pb_conn, next_be, pr_idx, 0) < 0) {
  670. goto free_and_return;
  671. }
  672. }
  673. next_be = NULL; /* to break the loop */
  674. } else if (PAGEDRESULTS_PAGE_END == pr_stat) {
  675. next_be = NULL; /* to break the loop */
  676. }
  677. } else {
  678. /* be_suffix null means that we are searching the default backend
  679. * -> don't change the search parameters in pblock
  680. */
  681. if (be_suffix != NULL)
  682. {
  683. if ((be_name == NULL) && (scope == LDAP_SCOPE_ONELEVEL))
  684. {
  685. /* one level searches
  686. * - depending on the suffix of the backend we might have to
  687. * do a one level search or a base search
  688. * - we might also have to change the search target
  689. */
  690. if (slapi_sdn_isparent(basesdn, be_suffix) ||
  691. (slapi_sdn_get_ndn_len(basesdn) == 0))
  692. {
  693. int tmp_scope = LDAP_SCOPE_BASE;
  694. slapi_pblock_set(pb, SLAPI_SEARCH_SCOPE, &tmp_scope);
  695. if (free_sdn) {
  696. slapi_pblock_get(pb, SLAPI_SEARCH_TARGET_SDN, &sdn);
  697. slapi_sdn_free(&sdn);
  698. }
  699. sdn = slapi_sdn_dup(be_suffix);
  700. slapi_pblock_set(pb, SLAPI_SEARCH_TARGET_SDN, (void *)sdn);
  701. free_sdn = 1;
  702. }
  703. else if (slapi_sdn_issuffix(basesdn, be_suffix))
  704. {
  705. int tmp_scope = LDAP_SCOPE_ONELEVEL;
  706. slapi_pblock_set(pb, SLAPI_SEARCH_SCOPE, &tmp_scope);
  707. }
  708. else
  709. goto next_be;
  710. }
  711. /* subtree searches :
  712. * if the search was started above the backend suffix
  713. * - temporarily set the SLAPI_SEARCH_TARGET_SDN to the
  714. * base of the node so that we don't get a NO SUCH OBJECT error
  715. * - do not change the scope
  716. */
  717. if (scope == LDAP_SCOPE_SUBTREE)
  718. {
  719. if (slapi_sdn_issuffix(be_suffix, basesdn))
  720. {
  721. if (free_sdn) {
  722. slapi_pblock_get(pb, SLAPI_SEARCH_TARGET_SDN, &sdn);
  723. slapi_sdn_free(&sdn);
  724. }
  725. sdn = slapi_sdn_dup(be_suffix);
  726. slapi_pblock_set(pb, SLAPI_SEARCH_TARGET_SDN, (void *)sdn);
  727. free_sdn = 1;
  728. }
  729. }
  730. }
  731. slapi_pblock_set(pb, SLAPI_BACKEND, be);
  732. slapi_pblock_set(pb, SLAPI_PLUGIN, be->be_database);
  733. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_SET, NULL);
  734. /* ONREPL - we need to be able to tell the backend not to send results directly */
  735. rc = (*be->be_search)(pb);
  736. switch (rc)
  737. {
  738. case 1:
  739. /* if the backend returned LDAP_NO_SUCH_OBJECT for a SEARCH request,
  740. * it will not have sent back a result - otherwise, it will have
  741. * sent a result */
  742. rc = SLAPI_FAIL_GENERAL;
  743. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &err);
  744. if (err == LDAP_NO_SUCH_OBJECT)
  745. {
  746. /* may be the object exist somewhere else
  747. * wait the end of the loop to send back this error
  748. */
  749. flag_no_such_object = 1;
  750. } else {
  751. /* err something other than LDAP_NO_SUCH_OBJECT, so the backend will
  752. * have sent the result -
  753. * Set a flag here so we don't return another result. */
  754. sent_result = 1;
  755. }
  756. /* fall through */
  757. case -1: /* an error occurred */
  758. /* PAGED RESULTS */
  759. if (op_is_pagedresults(operation)) {
  760. /* cleanup the slot */
  761. PR_EnterMonitor(pb->pb_conn->c_mutex);
  762. pagedresults_set_search_result(pb->pb_conn, operation, NULL, 1, pr_idx);
  763. rc = pagedresults_set_current_be(pb->pb_conn, NULL, pr_idx, 1);
  764. PR_ExitMonitor(pb->pb_conn->c_mutex);
  765. }
  766. if (1 == flag_no_such_object) {
  767. break;
  768. }
  769. slapi_pblock_get(pb, SLAPI_RESULT_CODE, &err);
  770. if (err == LDAP_NO_SUCH_OBJECT)
  771. {
  772. /* may be the object exist somewhere else
  773. * wait the end of the loop to send back this error
  774. */
  775. flag_no_such_object = 1;
  776. break;
  777. }
  778. else
  779. {
  780. /* for error other than LDAP_NO_SUCH_OBJECT
  781. * the error has already been sent
  782. * stop the search here
  783. */
  784. goto free_and_return;
  785. }
  786. /* when rc == SLAPI_FAIL_DISKFULL this case is executed */
  787. case SLAPI_FAIL_DISKFULL:
  788. operation_out_of_disk_space();
  789. goto free_and_return;
  790. case 0: /* search was successful and we need to send the result */
  791. flag_search_base_found++;
  792. rc = send_results_ext (pb, 1, &pnentries, pagesize, &pr_stat);
  793. /* PAGED RESULTS */
  794. if (op_is_pagedresults(operation)) {
  795. void *sr = NULL;
  796. int with_sort = operation->o_flags & OP_FLAG_SERVER_SIDE_SORTING;
  797. curr_search_count = pnentries;
  798. slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET, &sr);
  799. if ((PAGEDRESULTS_SEARCH_END == pr_stat) || (0 == pnentries)) {
  800. /* no more entries, but at least another backend */
  801. PR_EnterMonitor(pb->pb_conn->c_mutex);
  802. pagedresults_set_search_result(pb->pb_conn, operation, NULL, 1, pr_idx);
  803. be->be_search_results_release(&sr);
  804. rc = pagedresults_set_current_be(pb->pb_conn, next_be, pr_idx, 1);
  805. PR_ExitMonitor(pb->pb_conn->c_mutex);
  806. pr_stat = PAGEDRESULTS_SEARCH_END; /* make sure stat is SEARCH_END */
  807. if (NULL == next_be) {
  808. /* no more entries && no more backends */
  809. curr_search_count = -1;
  810. } else if (rc < 0) {
  811. goto free_and_return;
  812. }
  813. } else {
  814. curr_search_count = pnentries;
  815. slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_SET_SIZE_ESTIMATE, &estimate);
  816. pagedresults_lock(pb->pb_conn, pr_idx);
  817. if ((pagedresults_set_current_be(pb->pb_conn, be, pr_idx, 0) < 0) ||
  818. (pagedresults_set_search_result(pb->pb_conn, operation, sr, 0, pr_idx) < 0) ||
  819. (pagedresults_set_search_result_count(pb->pb_conn, operation, curr_search_count, pr_idx) < 0) ||
  820. (pagedresults_set_search_result_set_size_estimate(pb->pb_conn, operation, estimate, pr_idx) < 0) ||
  821. (pagedresults_set_with_sort(pb->pb_conn, operation, with_sort, pr_idx) < 0)) {
  822. pagedresults_unlock(pb->pb_conn, pr_idx);
  823. goto free_and_return;
  824. }
  825. pagedresults_unlock(pb->pb_conn, pr_idx);
  826. }
  827. slapi_pblock_set( pb, SLAPI_SEARCH_RESULT_SET, NULL );
  828. next_be = NULL; /* to break the loop */
  829. if (operation->o_status & SLAPI_OP_STATUS_ABANDONED) {
  830. /* It turned out this search was abandoned. */
  831. PR_EnterMonitor(pb->pb_conn->c_mutex);
  832. pagedresults_free_one_msgid_nolock( pb->pb_conn, operation->o_msgid);
  833. PR_ExitMonitor(pb->pb_conn->c_mutex);
  834. /* paged-results-request was abandoned; making an empty cookie. */
  835. pagedresults_set_response_control(pb, 0, estimate, -1, pr_idx);
  836. send_ldap_result(pb, 0, NULL, "Simple Paged Results Search abandoned", 0, NULL);
  837. rc = LDAP_SUCCESS;
  838. goto free_and_return;
  839. }
  840. pagedresults_set_response_control(pb, 0, estimate, curr_search_count, pr_idx);
  841. if (curr_search_count == -1) {
  842. pagedresults_free_one(pb->pb_conn, operation, pr_idx);
  843. }
  844. }
  845. /* if rc != 0 an error occurred while sending back the entries
  846. * to the LDAP client
  847. * LDAP error should already have been sent to the client
  848. * stop the search, free and return
  849. */
  850. if (rc != 0)
  851. goto free_and_return;
  852. break;
  853. }
  854. }
  855. nentries += pnentries;
  856. next_be:
  857. be = next_be; /* this be won't be used for PAGED_RESULTS */
  858. }
  859. /* if referrals were sent back by the mapping tree
  860. * add them to the list of referral in the pblock instead
  861. * of searching the backend
  862. */
  863. index = 0;
  864. while ((referral = referral_list[index++]) != NULL)
  865. {
  866. slapi_pblock_set(pb, SLAPI_BACKEND, NULL);
  867. if (err_code == LDAP_REFERRAL)
  868. {
  869. send_referrals_from_entry(pb,referral);
  870. goto free_and_return;
  871. }
  872. else
  873. {
  874. if (process_entry(pb, referral, 1))
  875. {
  876. flag_referral++;
  877. }
  878. else
  879. {
  880. /* Manage DSA was set, referral must be sent as an entry */
  881. int attrsonly;
  882. char **attrs = NULL;
  883. slapi_pblock_get(pb, SLAPI_SEARCH_ATTRS, &attrs);
  884. slapi_pblock_get(pb, SLAPI_SEARCH_ATTRSONLY, &attrsonly);
  885. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, referral);
  886. switch (send_ldap_search_entry(pb, referral, NULL, attrs, attrsonly))
  887. {
  888. case 0:
  889. flag_search_base_found++;
  890. nentries++;
  891. break;
  892. case 1: /* entry not sent */
  893. case -1: /* connection closed */
  894. break;
  895. }
  896. }
  897. }
  898. }
  899. if (flag_search_base_found || flag_referral) {
  900. rc = 0;
  901. }
  902. /* ONREPL - we currently call postop only if operation is successful;
  903. We should always send result and pass error code to the plugin */
  904. if (rc == 0) {
  905. plugin_call_plugins(pb, SLAPI_PLUGIN_POST_SEARCH_FN);
  906. }
  907. else
  908. {
  909. plugin_call_plugins(pb, SLAPI_PLUGIN_POST_SEARCH_FAIL_FN);
  910. }
  911. if (send_result) {
  912. if (rc == 0)
  913. {
  914. /* at least one backend returned something and there was no critical error
  915. * from the LDAP client point of view the search was successful
  916. */
  917. struct berval **urls = NULL;
  918. slapi_pblock_get(pb, SLAPI_SEARCH_REFERRALS, &urls);
  919. send_ldap_result(pb, err_code, NULL, NULL, nentries, urls);
  920. }
  921. else if (flag_no_such_object)
  922. {
  923. /* there was at least 1 backend that was called to process
  924. * the operation and all backends returned NO SUCH OBJECTS.
  925. * Don't send the result if it's already been handled above.
  926. */
  927. if (!sent_result) {
  928. slapi_send_ldap_result_from_pb(pb);
  929. }
  930. }
  931. else
  932. {
  933. /* No backend was found in the mapping tree to process
  934. * the operation : return NO SUCH OBJECT
  935. */
  936. send_ldap_result(pb, LDAP_NO_SUCH_OBJECT, NULL, NULL, 0, NULL);
  937. }
  938. } else {
  939. /* persistent search: ignore error locating base entry */
  940. rc = 0;
  941. }
  942. free_and_return:
  943. if ((be_list[0] != NULL) || (referral_list[0] != NULL)) {
  944. slapi_mapping_tree_free_all(be_list, referral_list);
  945. } else if (be_single) {
  946. slapi_be_Unlock(be_single);
  947. }
  948. free_and_return_nolock:
  949. slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, &rc);
  950. index_subsys_filter_decoders_done(pb);
  951. if (free_sdn) {
  952. slapi_pblock_get(pb, SLAPI_SEARCH_TARGET_SDN, &sdn);
  953. slapi_sdn_free(&sdn);
  954. }
  955. slapi_sdn_free(&basesdn);
  956. slapi_pblock_set(pb, SLAPI_SEARCH_TARGET_SDN, orig_sdn);
  957. slapi_ch_free_string(&proxydn);
  958. slapi_ch_free_string(&proxystr);
  959. }
  960. /* Returns 1 if this processing on this entry is finished
  961. * and doesn't need to be sent.
  962. */
  963. static int
  964. process_entry(Slapi_PBlock *pb, Slapi_Entry *e, int send_result)
  965. {
  966. int managedsait;
  967. Slapi_Attr *a=NULL;
  968. int numValues=0, i;
  969. if (!send_result)
  970. {
  971. /* server requested that we don't send results to the client,
  972. for instance, in case of a persistent search
  973. */
  974. return 1;
  975. }
  976. /* ONREPL - check if the entry should be referred (because of the copyingFrom) */
  977. /*
  978. * If this is a referral, and the managedsait control is not present,
  979. * arrange for a referral to be sent. For v2 connections,
  980. * the referrals are just squirreled away and sent with the
  981. * final result. For v3, the referrals are sent in separate LDAP messages.
  982. */
  983. slapi_pblock_get(pb, SLAPI_MANAGEDSAIT, &managedsait);
  984. if (!managedsait && slapi_entry_attr_find(e, "ref", &a)== 0)
  985. {
  986. /* to fix 522189: when rootDSE, don't interpret attribute ref as a referral entry */
  987. if ( slapi_is_rootdse(slapi_entry_get_dn_const(e)) )
  988. return 0; /* more to do for this entry, e.g., send it back to the client */
  989. /* end fix */
  990. slapi_attr_get_numvalues(a, &numValues );
  991. if (numValues == 0)
  992. {
  993. LDAPDebug1Arg(LDAP_DEBUG_ANY, "null ref in (%s)\n",
  994. slapi_entry_get_dn_const(e));
  995. }
  996. else
  997. {
  998. Slapi_Value *val=NULL;
  999. struct berval **refscopy=NULL;
  1000. struct berval **urls, **tmpUrls=NULL;
  1001. tmpUrls=(struct berval **) slapi_ch_malloc((numValues + 1) * sizeof(struct berval*));
  1002. for ( i = slapi_attr_first_value(a, &val); i != -1;
  1003. i = slapi_attr_next_value(a, i, &val)) {
  1004. tmpUrls[i]=(struct berval*)slapi_value_get_berval(val);
  1005. }
  1006. tmpUrls[numValues]=NULL;
  1007. refscopy = ref_adjust(pb, tmpUrls, slapi_entry_get_sdn_const(e), 1);
  1008. slapi_pblock_get(pb, SLAPI_SEARCH_REFERRALS, &urls);
  1009. send_ldap_referral(pb, e, refscopy, &urls);
  1010. slapi_pblock_set(pb, SLAPI_SEARCH_REFERRALS, urls);
  1011. if (NULL != refscopy)
  1012. {
  1013. ber_bvecfree(refscopy);
  1014. refscopy = NULL;
  1015. }
  1016. slapi_ch_free( (void **)&tmpUrls );
  1017. }
  1018. return 1; /* done with this entry */
  1019. }
  1020. return 0;
  1021. }
  1022. #if 0
  1023. /* Loops through search entries and sends them to the client.
  1024. * returns -1 on error, 0 if result packet was sent or 1 if
  1025. * result packet wasn't sent
  1026. */
  1027. static int
  1028. iterate_with_lookahead(Slapi_PBlock *pb, Slapi_Backend *be, int send_result, int *pnentries)
  1029. {
  1030. int rc;
  1031. int attrsonly;
  1032. int done = 0;
  1033. Slapi_Entry *e;
  1034. void *backend_info_ptr;
  1035. Slapi_Entry *next_e;
  1036. void *next_backend_info_ptr;
  1037. char **attrs = NULL;
  1038. int send_result_status = 0;
  1039. slapi_pblock_get(pb, SLAPI_SEARCH_ATTRS, &attrs);
  1040. slapi_pblock_get(pb, SLAPI_SEARCH_ATTRSONLY, &attrsonly);
  1041. /* setup for the loop */
  1042. rc = be->be_next_search_entry_ext(pb, 1);
  1043. if (rc < 0)
  1044. {
  1045. /*
  1046. * Some exceptional condition occurred. Results
  1047. * have been sent, so we're finished.
  1048. */
  1049. if (rc == SLAPI_FAIL_DISKFULL)
  1050. {
  1051. operation_out_of_disk_space();
  1052. }
  1053. return -1;
  1054. }
  1055. slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_ENTRY, &next_e);
  1056. slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_ENTRY_EXT, &next_backend_info_ptr);
  1057. if (NULL == next_e)
  1058. {
  1059. /* no entries */
  1060. done = 1;
  1061. }
  1062. backend_info_ptr = NULL;
  1063. /* Done setting up the loop, now here it comes */
  1064. while (!done)
  1065. {
  1066. /* Allow the backend to free the entry we just finished using */
  1067. /* It is ok to call this when backend_info_ptr is NULL */
  1068. be->be_entry_release(pb, backend_info_ptr);
  1069. e = next_e;
  1070. backend_info_ptr = next_backend_info_ptr;
  1071. rc = be->be_next_search_entry_ext(pb, 1);
  1072. if (rc < 0)
  1073. {
  1074. /*
  1075. * Some exceptional condition occurred. Results
  1076. * have been sent, so we're finished.
  1077. */
  1078. if (rc == SLAPI_FAIL_DISKFULL)
  1079. {
  1080. operation_out_of_disk_space();
  1081. }
  1082. return -1;
  1083. }
  1084. else
  1085. {
  1086. slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_ENTRY, &next_e);
  1087. slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_ENTRY_EXT, &next_backend_info_ptr);
  1088. if (next_e == NULL)
  1089. {
  1090. /* no more entries */
  1091. done = 1;
  1092. }
  1093. }
  1094. if (process_entry(pb, e, send_result))
  1095. {
  1096. /* shouldn't send this entry */
  1097. continue;
  1098. }
  1099. /*
  1100. * It's a regular entry, or it's a referral and
  1101. * managedsait control is on. In either case, send the entry.
  1102. */
  1103. if (done)
  1104. {
  1105. struct berval **urls = NULL;
  1106. /* Send the entry and the result at the same time */
  1107. slapi_pblock_get(pb, SLAPI_SEARCH_REFERRALS, &urls);
  1108. rc = send_ldap_search_entry_ext(pb, e, NULL, attrs, attrsonly, 1,
  1109. (*pnentries)+1, urls);
  1110. if (rc == 1)
  1111. {
  1112. /* this means we didn't have access to the entry. Since the
  1113. * entry was not sent, we need to send the done packet.
  1114. */
  1115. send_result_status = 1;
  1116. }
  1117. }
  1118. else
  1119. {
  1120. /* Send the entry */
  1121. rc = send_ldap_search_entry(pb, e, NULL, attrs,
  1122. attrsonly);
  1123. }
  1124. switch (rc)
  1125. {
  1126. case 0: /* entry sent ok */
  1127. (*pnentries)++;
  1128. slapi_pblock_set(pb, SLAPI_NENTRIES, pnentries);
  1129. break;
  1130. case 1: /* entry not sent */
  1131. break;
  1132. case -1: /* connection closed */
  1133. /*
  1134. * mark the operation as abandoned so the backend
  1135. * next entry function gets called again and has
  1136. * a chance to clean things up.
  1137. */
  1138. pb->pb_op->o_status = SLAPI_OP_STATUS_ABANDONED;
  1139. break;
  1140. }
  1141. }
  1142. be->be_entry_release(pb, backend_info_ptr);
  1143. if (*pnentries == 0 || send_result_status)
  1144. {
  1145. /* We didn't send the result done message so the caller
  1146. * must send it */
  1147. return 1;
  1148. }
  1149. else
  1150. {
  1151. /* The result message has been sent */
  1152. return 0;
  1153. }
  1154. }
  1155. #endif
  1156. /* Loops through search entries and sends them to the client.
  1157. * returns -1 on error or 1 if result packet wasn't sent.
  1158. * This function never returns 0 because it doesn't send
  1159. * the result packet back with the last entry like
  1160. * iterate_with_lookahead trys to do.
  1161. */
  1162. static int
  1163. iterate(Slapi_PBlock *pb, Slapi_Backend *be, int send_result,
  1164. int *pnentries, int pagesize, unsigned int *pr_statp)
  1165. {
  1166. int rc;
  1167. int rval = 1; /* no error, by default */
  1168. int attrsonly;
  1169. int done = 0;
  1170. Slapi_Entry *e = NULL;
  1171. char **attrs = NULL;
  1172. unsigned int pr_stat = 0;
  1173. int pr_idx = -1;
  1174. if ( NULL == pb ) {
  1175. return rval;
  1176. }
  1177. slapi_pblock_get(pb, SLAPI_SEARCH_ATTRS, &attrs);
  1178. slapi_pblock_get(pb, SLAPI_SEARCH_ATTRSONLY, &attrsonly);
  1179. slapi_pblock_get(pb, SLAPI_PAGED_RESULTS_INDEX, &pr_idx);
  1180. *pnentries = 0;
  1181. while (!done)
  1182. {
  1183. Slapi_Entry *gerentry = NULL;
  1184. Slapi_Operation *operation;
  1185. slapi_pblock_get (pb, SLAPI_OPERATION, &operation);
  1186. rc = be->be_next_search_entry(pb);
  1187. if (rc < 0)
  1188. {
  1189. /*
  1190. * Some exceptional condition occurred. Results have been sent,
  1191. * so we're finished.
  1192. */
  1193. if (rc == SLAPI_FAIL_DISKFULL)
  1194. {
  1195. operation_out_of_disk_space();
  1196. }
  1197. pr_stat = PAGEDRESULTS_SEARCH_END;
  1198. rval = -1;
  1199. done = 1;
  1200. continue;
  1201. }
  1202. slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_ENTRY, &e);
  1203. /* Check for possible get_effective_rights control */
  1204. if (e) {
  1205. if (operation->o_flags & OP_FLAG_GET_EFFECTIVE_RIGHTS) {
  1206. char *errbuf = NULL;
  1207. char **gerattrs = NULL;
  1208. char **gerattrsdup = NULL;
  1209. char **gap = NULL;
  1210. char *gapnext = NULL;
  1211. if (PAGEDRESULTS_PAGE_END == pr_stat)
  1212. {
  1213. /*
  1214. * read ahead -- there is at least more entry.
  1215. * undo it and return the PAGE_END
  1216. */
  1217. be->be_prev_search_results(pb);
  1218. done = 1;
  1219. continue;
  1220. }
  1221. slapi_pblock_get( pb, SLAPI_SEARCH_GERATTRS, &gerattrs );
  1222. gerattrsdup = cool_charray_dup(gerattrs);
  1223. gap = gerattrsdup;
  1224. do
  1225. {
  1226. gapnext = NULL;
  1227. if (gap)
  1228. {
  1229. if (*gap && *(gap+1))
  1230. {
  1231. gapnext = *(gap+1);
  1232. *(gap+1) = NULL;
  1233. }
  1234. slapi_pblock_set( pb, SLAPI_SEARCH_GERATTRS, gap );
  1235. rc = plugin_call_acl_plugin (pb, e, attrs, NULL,
  1236. SLAPI_ACL_ALL, ACLPLUGIN_ACCESS_GET_EFFECTIVE_RIGHTS,
  1237. &errbuf);
  1238. if (NULL != gapnext)
  1239. {
  1240. *(gap+1) = gapnext;
  1241. }
  1242. }
  1243. else if (NULL != e)
  1244. {
  1245. rc = plugin_call_acl_plugin (pb, e, attrs, NULL,
  1246. SLAPI_ACL_ALL, ACLPLUGIN_ACCESS_GET_EFFECTIVE_RIGHTS,
  1247. &errbuf);
  1248. }
  1249. if (NULL == e) {
  1250. /* get the template entry, if any */
  1251. slapi_pblock_get(pb, SLAPI_SEARCH_RESULT_ENTRY, &e);
  1252. if (NULL == e) {
  1253. /* everything is ok - don't send the result */
  1254. pr_stat = PAGEDRESULTS_SEARCH_END;
  1255. done = 1;
  1256. continue;
  1257. }
  1258. gerentry = e;
  1259. }
  1260. if ( rc != LDAP_SUCCESS ) {
  1261. /* Send error result and
  1262. abort op if the control is critical */
  1263. LDAPDebug( LDAP_DEBUG_ANY,
  1264. "Failed to get effective rights for entry (%s), rc=%d\n",
  1265. slapi_entry_get_dn_const(e), rc, 0 );
  1266. send_ldap_result( pb, rc, NULL, errbuf, 0, NULL );
  1267. slapi_ch_free ( (void**)&errbuf );
  1268. if (gerentry)
  1269. {
  1270. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, NULL);
  1271. slapi_entry_free(gerentry);
  1272. gerentry = e = NULL;
  1273. }
  1274. pr_stat = PAGEDRESULTS_SEARCH_END;
  1275. rval = -1;
  1276. done = 1;
  1277. continue;
  1278. }
  1279. slapi_ch_free ( (void**)&errbuf );
  1280. if (process_entry(pb, e, send_result))
  1281. {
  1282. /* shouldn't send this entry */
  1283. if (gerentry)
  1284. {
  1285. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, NULL);
  1286. slapi_entry_free(gerentry);
  1287. gerentry = e = NULL;
  1288. }
  1289. continue;
  1290. }
  1291. /*
  1292. * It's a regular entry, or it's a referral and
  1293. * managedsait control is on. In either case, send
  1294. * the entry.
  1295. */
  1296. switch (send_ldap_search_entry(pb, e, NULL, attrs, attrsonly))
  1297. {
  1298. case 0: /* entry sent ok */
  1299. (*pnentries)++;
  1300. slapi_pblock_set(pb, SLAPI_NENTRIES, pnentries);
  1301. break;
  1302. case 1: /* entry not sent */
  1303. break;
  1304. case -1: /* connection closed */
  1305. /*
  1306. * mark the operation as abandoned so the backend
  1307. * next entry function gets called again and has
  1308. * a chance to clean things up.
  1309. */
  1310. pb->pb_op->o_status = SLAPI_OP_STATUS_ABANDONED;
  1311. break;
  1312. }
  1313. if (gerentry)
  1314. {
  1315. slapi_pblock_set(pb, SLAPI_SEARCH_RESULT_ENTRY, NULL);
  1316. slapi_entry_free(gerentry);
  1317. gerentry = e = NULL;
  1318. }
  1319. }
  1320. while (gap && ++gap && *gap);
  1321. slapi_pblock_set( pb, SLAPI_SEARCH_GERATTRS, gerattrs );
  1322. cool_charray_free(gerattrsdup);
  1323. if (pagesize == *pnentries)
  1324. {
  1325. /* PAGED RESULTS: reached the pagesize */
  1326. /* We don't set "done = 1" here.
  1327. * We read ahead next entry to check whether there is
  1328. * more entries to return or not. */
  1329. pr_stat = PAGEDRESULTS_PAGE_END;
  1330. }
  1331. } else { /* not GET_EFFECTIVE_RIGHTS */
  1332. if (PAGEDRESULTS_PAGE_END == pr_stat)
  1333. {
  1334. /*
  1335. * read ahead -- there is at least more entry.
  1336. * undo it and return the PAGE_END
  1337. */
  1338. be->be_prev_search_results(pb);
  1339. done = 1;
  1340. continue;
  1341. }
  1342. /* Adding shadow password attrs. */
  1343. add_shadow_ext_password_attrs(pb, &e);
  1344. if (process_entry(pb, e, send_result))
  1345. {
  1346. /* shouldn't send this entry */
  1347. slapi_entry_free(pb->pb_pw_entry);
  1348. pb->pb_pw_entry = NULL;
  1349. continue;
  1350. }
  1351. /*
  1352. * It's a regular entry, or it's a referral and
  1353. * managedsait control is on. In either case, send
  1354. * the entry.
  1355. */
  1356. switch (send_ldap_search_entry(pb, e, NULL, attrs, attrsonly))
  1357. {
  1358. case 0: /* entry sent ok */
  1359. (*pnentries)++;
  1360. slapi_pblock_set(pb, SLAPI_NENTRIES, pnentries);
  1361. break;
  1362. case 1: /* entry not sent */
  1363. break;
  1364. case -1: /* connection closed */
  1365. /*
  1366. * mark the operation as abandoned so the backend
  1367. * next entry function gets called again and has
  1368. * a chance to clean things up.
  1369. */
  1370. pb->pb_op->o_status = SLAPI_OP_STATUS_ABANDONED;
  1371. break;
  1372. }
  1373. slapi_entry_free(pb->pb_pw_entry);
  1374. pb->pb_pw_entry = NULL;
  1375. if (pagesize == *pnentries)
  1376. {
  1377. /* PAGED RESULTS: reached the pagesize */
  1378. /* We don't set "done = 1" here.
  1379. * We read ahead next entry to check whether there is
  1380. * more entries to return or not. */
  1381. pr_stat = PAGEDRESULTS_PAGE_END;
  1382. }
  1383. }
  1384. }
  1385. else
  1386. {
  1387. /* no more entries */
  1388. done = 1;
  1389. pr_stat = PAGEDRESULTS_SEARCH_END;
  1390. }
  1391. }
  1392. if (pr_statp) {
  1393. *pr_statp = pr_stat;
  1394. }
  1395. return rval;
  1396. }
  1397. static int timelimit_reslimit_handle = -1;
  1398. static int sizelimit_reslimit_handle = -1;
  1399. static int pagedsizelimit_reslimit_handle = -1;
  1400. /*
  1401. * Register size and time limit with the binder-based resource limits
  1402. * subsystem. A SLAPI_RESLIMIT_STATUS_... code is returned.
  1403. */
  1404. int
  1405. search_register_reslimits( void )
  1406. {
  1407. int rc1, rc2, rc3;
  1408. rc1 = slapi_reslimit_register( SLAPI_RESLIMIT_TYPE_INT,
  1409. "nsSizeLimit" , &sizelimit_reslimit_handle );
  1410. rc2 = slapi_reslimit_register( SLAPI_RESLIMIT_TYPE_INT,
  1411. "nsTimeLimit", &timelimit_reslimit_handle );
  1412. rc3 = slapi_reslimit_register( SLAPI_RESLIMIT_TYPE_INT,
  1413. "nsPagedSizeLimit", &pagedsizelimit_reslimit_handle );
  1414. return (rc1 != SLAPI_RESLIMIT_STATUS_SUCCESS) ? rc1 :
  1415. ((rc2 != SLAPI_RESLIMIT_STATUS_SUCCESS) ? rc2 : rc3);
  1416. }
  1417. /*
  1418. * Compute size and time limits based on the connection (bind identity).
  1419. * Binder-based resource limits get top priority, followed by those associated
  1420. * with the backend we are using.
  1421. *
  1422. * If the binder is the root DN and there is nothing in the root DN's entry
  1423. * to say otherwise, no limits are used. Otherwise, the lower of the limit
  1424. * that was sent in the LDAP request and that available based on the
  1425. * connection bind identity or configured backend limit is used.
  1426. */
  1427. static void
  1428. compute_limits (Slapi_PBlock *pb)
  1429. {
  1430. int timelimit, sizelimit;
  1431. int requested_timelimit, max_timelimit, requested_sizelimit, max_sizelimit;
  1432. int isroot;
  1433. int isCertAuth;
  1434. Slapi_ComponentId *component_id = NULL;
  1435. Slapi_Backend *be;
  1436. Slapi_Operation *op;
  1437. slapi_pblock_get (pb, SLAPI_SEARCH_TIMELIMIT, &requested_timelimit);
  1438. slapi_pblock_get (pb, SLAPI_SEARCH_SIZELIMIT, &requested_sizelimit);
  1439. slapi_pblock_get (pb, SLAPI_REQUESTOR_ISROOT, &isroot);
  1440. slapi_pblock_get (pb, SLAPI_BACKEND, &be);
  1441. slapi_pblock_get (pb, SLAPI_OPERATION, &op);
  1442. /* If the search belongs to the client authentication process, take the value at
  1443. * nsslapd-timelimit as the actual time limit.
  1444. */
  1445. slapi_pblock_get (pb, SLAPI_PLUGIN_IDENTITY, &component_id);
  1446. if (component_id) {
  1447. isCertAuth = (! strcasecmp(component_id->sci_component_name, COMPONENT_CERT_AUTH) ) ? 1 : 0;
  1448. if (isCertAuth) {
  1449. timelimit = config_get_timelimit();
  1450. goto set_timelimit;
  1451. }
  1452. }
  1453. /*
  1454. * Compute the time limit.
  1455. */
  1456. if ( slapi_reslimit_get_integer_limit( pb->pb_conn,
  1457. timelimit_reslimit_handle, &max_timelimit )
  1458. != SLAPI_RESLIMIT_STATUS_SUCCESS ) {
  1459. /*
  1460. * no limit associated with binder/connection or some other error
  1461. * occurred. use the default maximum.
  1462. */
  1463. if ( isroot ) {
  1464. max_timelimit = -1; /* no limit */
  1465. } else {
  1466. max_timelimit = be->be_timelimit;
  1467. }
  1468. }
  1469. if ( requested_timelimit ) {
  1470. /* requested limit should be applied to all (including root) */
  1471. if ( isroot ) {
  1472. timelimit = requested_timelimit;
  1473. } else if ( (max_timelimit == -1) ||
  1474. (requested_timelimit < max_timelimit) ) {
  1475. timelimit = requested_timelimit;
  1476. } else {
  1477. timelimit = max_timelimit;
  1478. }
  1479. } else if ( isroot ) {
  1480. timelimit = -1; /* no limit */
  1481. } else {
  1482. timelimit = max_timelimit;
  1483. }
  1484. set_timelimit:
  1485. slapi_pblock_set(pb, SLAPI_SEARCH_TIMELIMIT, &timelimit);
  1486. /*
  1487. * Compute the size limit.
  1488. */
  1489. if ( slapi_reslimit_get_integer_limit( pb->pb_conn,
  1490. sizelimit_reslimit_handle, &max_sizelimit )
  1491. != SLAPI_RESLIMIT_STATUS_SUCCESS ) {
  1492. /*
  1493. * no limit associated with binder/connection or some other error
  1494. * occurred. use the default maximum.
  1495. */
  1496. if ( isroot ) {
  1497. max_sizelimit = -1; /* no limit */
  1498. } else {
  1499. max_sizelimit = be->be_sizelimit;
  1500. }
  1501. }
  1502. if (op_is_pagedresults(op)) {
  1503. if ( slapi_reslimit_get_integer_limit( pb->pb_conn,
  1504. pagedsizelimit_reslimit_handle, &max_sizelimit )
  1505. != SLAPI_RESLIMIT_STATUS_SUCCESS ) {
  1506. /*
  1507. * no limit associated with binder/connection or some other error
  1508. * occurred. use the default maximum.
  1509. */
  1510. if ( be->be_pagedsizelimit ) {
  1511. max_sizelimit = be->be_pagedsizelimit;
  1512. }
  1513. /* else was already set above */
  1514. }
  1515. }
  1516. if ( requested_sizelimit ) {
  1517. /* requested limit should be applied to all (including root) */
  1518. if ( isroot ) {
  1519. sizelimit = requested_sizelimit;
  1520. } else if ( (max_sizelimit == -1) ||
  1521. (requested_sizelimit < max_sizelimit) ) {
  1522. sizelimit = requested_sizelimit;
  1523. } else {
  1524. sizelimit = max_sizelimit;
  1525. }
  1526. } else if ( isroot ) {
  1527. sizelimit = -1; /* no limit */
  1528. } else {
  1529. sizelimit = max_sizelimit;
  1530. }
  1531. slapi_pblock_set(pb, SLAPI_SEARCH_SIZELIMIT, &sizelimit);
  1532. LDAPDebug( LDAP_DEBUG_TRACE,
  1533. "=> compute_limits: sizelimit=%d, timelimit=%d\n",
  1534. sizelimit, timelimit, 0 );
  1535. }
  1536. /* Iterates through results and send them to the client.
  1537. * Returns 0 if successful and -1 otherwise
  1538. */
  1539. static int
  1540. send_results_ext(Slapi_PBlock *pb, int send_result, int *nentries, int pagesize, unsigned int *pr_stat)
  1541. {
  1542. Slapi_Backend *be;
  1543. int rc;
  1544. slapi_pblock_get (pb, SLAPI_BACKEND, &be);
  1545. if (be->be_next_search_entry == NULL)
  1546. {
  1547. /* we need to send the result, but the function to iterate through
  1548. the result set is not implemented */
  1549. /* ONREPL - log error */
  1550. send_ldap_result(pb, LDAP_UNWILLING_TO_PERFORM, NULL, "Search not supported", 0, NULL);
  1551. return -1;
  1552. }
  1553. /* Iterate through the returned result set */
  1554. if (be->be_next_search_entry_ext != NULL)
  1555. {
  1556. /* The iterate look ahead is causing a whole mess with the ACL.
  1557. ** the entries are now visiting the ACL land in a random way
  1558. ** and not the ordered way it was before. Until we figure out
  1559. ** let's not change the behavior.
  1560. **
  1561. ** Don't use iterate_with_lookahead because it sends the result
  1562. * in the same times as the entry and this can cause failure
  1563. * of the mapping tree scanning algorithme
  1564. * if (getFrontendConfig()->result_tweak)
  1565. * {
  1566. * rc = iterate_with_lookahead(pb, be, send_result, nentries);
  1567. * }
  1568. * else
  1569. */
  1570. rc = iterate(pb, be, send_result, nentries, pagesize, pr_stat);
  1571. }
  1572. else
  1573. {
  1574. rc = iterate(pb, be, send_result, nentries, pagesize, pr_stat);
  1575. }
  1576. switch(rc)
  1577. {
  1578. case -1: /* an error occured */
  1579. case 0 : /* everything is ok - result is sent */
  1580. /* If this happens we are dead but hopefully iterate
  1581. * never sends the result itself
  1582. */
  1583. break;
  1584. case 1: /* everything is ok - don't send the result */
  1585. rc = 0;
  1586. }
  1587. return rc;
  1588. }
  1589. void op_shared_log_error_access (Slapi_PBlock *pb, const char *type, const char *dn, const char *msg)
  1590. {
  1591. char *proxydn = NULL;
  1592. char *proxystr = NULL;
  1593. if ((proxyauth_get_dn(pb, &proxydn, NULL) == LDAP_SUCCESS)) {
  1594. proxystr = slapi_ch_smprintf(" authzid=\"%s\"", proxydn);
  1595. }
  1596. slapi_log_access( LDAP_DEBUG_STATS, "conn=%" NSPRIu64 " op=%d %s dn=\"%s\"%s, %s\n",
  1597. ( pb->pb_conn ? pb->pb_conn->c_connid : 0),
  1598. ( pb->pb_op ? pb->pb_op->o_opid : 0),
  1599. type,
  1600. dn,
  1601. proxystr ? proxystr : "",
  1602. msg ? msg : "" );
  1603. slapi_ch_free_string(&proxydn);
  1604. slapi_ch_free_string(&proxystr);
  1605. }